From f8e6f036affaaca135103556bd2c7f15a943d29b Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Sat, 1 Jul 2023 13:24:50 +0100 Subject: [PATCH] AsyncPoolTest: added failing test case for AsyncTask::__destruct() reentrancy bug --- tests/phpunit/scheduler/AsyncPoolTest.php | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/phpunit/scheduler/AsyncPoolTest.php b/tests/phpunit/scheduler/AsyncPoolTest.php index 9a61c33ff..42c301be3 100644 --- a/tests/phpunit/scheduler/AsyncPoolTest.php +++ b/tests/phpunit/scheduler/AsyncPoolTest.php @@ -69,4 +69,36 @@ class AsyncPoolTest extends TestCase{ } self::assertTrue(PublishProgressRaceAsyncTask::$success, "Progress was not reported before task completion"); } + + /** + * This test ensures that the fix for an exotic AsyncTask::__destruct() reentrancy bug has not regressed. + * + * Due to an unset() in the function body, other AsyncTask::__destruct() calls could be triggered during + * an AsyncTask's destruction. If done in the wrong way, this could lead to a crash. + * + * @doesNotPerformAssertions This test is checking for a crash condition, not a specific output. + */ + public function testTaskDestructorReentrancy() : void{ + $this->pool->submitTask(new class extends AsyncTask{ + public function __construct(){ + $this->storeLocal("task", new class extends AsyncTask{ + + public function __construct(){ + $this->storeLocal("dummy", 1); + } + + public function onRun() : void{ + //dummy + } + }); + } + + public function onRun() : void{ + //dummy + } + }); + while($this->pool->collectTasks()){ + usleep(50 * 1000); + } + } }