From b4f2cef76c964d5c2e47aafd631db17796cbd4f5 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 26 Jan 2021 15:54:09 -0800 Subject: [PATCH] Prevent interruption by the PHP "set_time_limit()" mechanism while holding the durable write lock Summary: Ref T13590. By default, PHP kills execution after web scripts run for 30 seconds. If this occurs in the locked section of a repository write while we're holding the durable write lock, the lock will get stuck. Use "set_time_limit(0)" to prevent this mechanism from interrupting execution while the durable lock is held. Test Plan: - Added "set_time_limit(1)" before the lock and "while (1);" in the critical section of the lock. - Pushed, got the lock stuck. - Cleared the lock, applied this patch, pushed. - Got an infinite hang instead. (Normally, we expect the script to take more than 30 seconds to execute because there is a large push that executes in finite time, not because there's an infinte loop.) Maniphest Tasks: T13590 Differential Revision: https://secure.phabricator.com/D21526 --- .../diffusion/protocol/DiffusionRepositoryClusterEngine.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php b/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php index 717e730ab1..2d815917a4 100644 --- a/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php +++ b/src/applications/diffusion/protocol/DiffusionRepositoryClusterEngine.php @@ -318,6 +318,11 @@ final class DiffusionRepositoryClusterEngine extends Phobject { 'Acquiring write lock for repository "%s"...', $repository->getDisplayName())); + // See T13590. On the HTTP pathway, it's possible for us to hit the script + // time limit while holding the durable write lock if a user makes a big + // push. Remove the time limit before we acquire the durable lock. + set_time_limit(0); + $lock_wait = phutil_units('2 minutes in seconds'); try { $write_wait_start = microtime(true);