diff --git a/lib/Phpfastcache/Extensions/Drivers/Couchbasev4/Driver.php b/lib/Phpfastcache/Extensions/Drivers/Couchbasev4/Driver.php index 380a94e..acea0fe 100644 --- a/lib/Phpfastcache/Extensions/Drivers/Couchbasev4/Driver.php +++ b/lib/Phpfastcache/Extensions/Drivers/Couchbasev4/Driver.php @@ -86,6 +86,11 @@ protected function driverConnect(): bool } if ($this->getConfig()->isDoForkDetection() && extension_loaded('posix')) { + // https://issues.couchbase.com/browse/PCBC-984 + if (version_compare($extVersion, '4.2.0', '=')) { + throw new PhpfastcacheDriverCheckException("You are using Couchbase extension $extVersion, This version has a known bug with pcntl_fork()"); + } + $this->currentParentPID = posix_getppid(); } diff --git a/tests/Couchbasev4.test.php b/tests/Couchbasev4.test.php index 269d2f0..61cfbee 100644 --- a/tests/Couchbasev4.test.php +++ b/tests/Couchbasev4.test.php @@ -21,7 +21,8 @@ chdir(__DIR__); require_once __DIR__ . '/../vendor/autoload.php'; -$testHelper = new TestHelper('Couchbasev4 driver'); +$extensionVersion = (new ReflectionExtension('couchbase'))->getVersion(); +$testHelper = new TestHelper('Couchbasev4 driver - Extension Version ' . $extensionVersion); $configFileName = __DIR__ . '/Configs/' . ($argv[1] ?? 'github-actions') . '.php'; if (!file_exists($configFileName)) { @@ -33,57 +34,74 @@ $config = (include $configFileName) ->setDoForkDetection(false) ->setUseStaticItemCaching(false); - -$cacheInstance = CacheManager::getInstance('Couchbasev4', $config); - -$cache = new Psr16Adapter($cacheInstance); -$value = random_int(1, 254); - -$cache->set('forkFailTestKey', $value); - -$pid = pcntl_fork(); -if ($pid == -1) { - $testHelper->assertFail('Unable to fork'); -} else if ($pid) { - $testHelper->runAsyncProcess('php "'.__DIR__ . '/Scripts/monitor_fork.php" ' . $pid); - pcntl_wait($status); -} else { - exit($cache->get('forkFailTestKey')); -} - -if ($value === pcntl_wexitstatus($status)) { - $testHelper->assertFail('The fork was a success was meant to lockup'); -} else { - $testHelper->assertPass('The forked process locked up has expected'); -} - -$testHelper->printInfoText('Running forking success process test'); - -$config = (include $configFileName) - ->setDoForkDetection(true) - ->setUseStaticItemCaching(false); - $cacheInstance = CacheManager::getInstance('Couchbasev4', $config); -$cache = new Psr16Adapter($cacheInstance); -$value = random_int(1, 254); - -$cache->set('forkSuccessTestKey', $value); - -$pid = pcntl_fork(); -if ($pid == -1) { - $testHelper->assertFail('Unable to fork'); -} else if ($pid) { - $testHelper->runAsyncProcess('php "'.__DIR__ . '/Scripts/monitor_fork.php" ' . $pid); - pcntl_wait($status); -} else { - exit($cache->get('forkSuccessTestKey')); -} - -if ($value === pcntl_wexitstatus($status)) { - $testHelper->assertPass('The exit code is the one expected'); +if (version_compare($extensionVersion, '4.2.0', '<')) { + $cache = new Psr16Adapter($cacheInstance); + $value = random_int(1, 254); + + $cache->set('forkFailTestKey', $value); + + $pid = pcntl_fork(); + if ($pid == -1) { + $testHelper->assertFail('Unable to fork'); + } else if ($pid) { + $testHelper->runAsyncProcess('php "' . __DIR__ . '/Scripts/monitor_fork.php" ' . $pid); + pcntl_wait($status); + } else { + exit($cache->get('forkFailTestKey')); + } + + if ($value === pcntl_wexitstatus($status)) { + $testHelper->assertFail('The fork was a success was meant to lockup'); + } else { + $testHelper->assertPass('The forked process locked up has expected'); + } + + $testHelper->printInfoText('Running forking success process test'); + + $config = (include $configFileName) + ->setDoForkDetection(true) + ->setUseStaticItemCaching(false); + + $cacheInstance = CacheManager::getInstance('Couchbasev4', $config); + + $cache = new Psr16Adapter($cacheInstance); + $value = random_int(1, 254); + + $cache->set('forkSuccessTestKey', $value); + + $pid = pcntl_fork(); + if ($pid == -1) { + $testHelper->assertFail('Unable to fork'); + } else if ($pid) { + $testHelper->runAsyncProcess('php "' . __DIR__ . '/Scripts/monitor_fork.php" ' . $pid); + pcntl_wait($status); + } else { + exit($cache->get('forkSuccessTestKey')); + } + + if ($value === pcntl_wexitstatus($status)) { + $testHelper->assertPass('The exit code is the one expected'); + } else { + $testHelper->assertFail('The exit code is unexpected'); + } } else { - $testHelper->assertFail('The exit code is unexpected'); + try { + CacheManager::getInstance( + 'Couchbasev4', + (include $configFileName) + ->setDoForkDetection(true) + ->setUseStaticItemCaching(false) + ); + + } catch (\Phpfastcache\Exceptions\PhpfastcacheDriverConnectException $exception) { + if (str_contains($exception->getMessage(), 'bug with pcntl_fork()')) { + $testHelper->assertPass('correctly failed fork test due to extension version check'); + } else { + $testHelper->assertFail('The exit code is unexpected'); + } + } } try {