diff --git a/.gitignore b/.gitignore index 9aec3a195..7383e0503 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ modules run-tests.php tags .lvimrc +mongocryptd.pid # phpt leftovers *.diff diff --git a/php_phongo.c b/php_phongo.c index 9f196e410..f66874f00 100644 --- a/php_phongo.c +++ b/php_phongo.c @@ -3596,6 +3596,11 @@ void php_phongo_client_reset_once(php_phongo_manager_t* manager, int pid) { php_phongo_pclient_t* pclient; + /* Reset associated key vault client */ + if (!Z_ISUNDEF(manager->key_vault_client_manager)) { + php_phongo_client_reset_once(Z_MANAGER_OBJ_P(&manager->key_vault_client_manager), pid); + } + if (manager->use_persistent_client) { pclient = zend_hash_str_find_ptr(&MONGODB_G(persistent_clients), manager->client_hash, manager->client_hash_len); diff --git a/tests/cursor/bug1529-001.phpt b/tests/cursor/bug1529-001.phpt new file mode 100644 index 000000000..ea1d982bc --- /dev/null +++ b/tests/cursor/bug1529-001.phpt @@ -0,0 +1,105 @@ +--TEST-- +PHPC-1529: Resetting a client should also reset the keyVaultClient +--SKIPIF-- + + + + + + +--FILE-- +pid = getmypid(); + } + + public function commandStarted(MongoDB\Driver\Monitoring\CommandStartedEvent $event) + { + $command = $event->getCommand(); + $commandName = $event->getCommandName(); + $process = $this->pid === getmypid() ? 'Parent' : 'Child'; + + if ($commandName === 'find' || $commandName === 'getMore') { + printf("%s executes %s with batchSize: %d\n", $process, $commandName, $command->batchSize); + return; + } + + printf("%s executes %s\n", $process, $commandName); + } + + public function commandSucceeded(MongoDB\Driver\Monitoring\CommandSucceededEvent $event) + { + } + + public function commandFailed(MongoDB\Driver\Monitoring\CommandFailedEvent $event) + { + } +} + +$keyVaultClient = new MongoDB\Driver\Manager(URI, [], ['disableClientPersistence' => true]); +$autoEncryptionOpts = [ + 'keyVaultClient' => $keyVaultClient, + 'keyVaultNamespace' => 'default.keys', + 'kmsProviders' => ['local' => ['key' => new MongoDB\BSON\Binary(str_repeat('0', 96), 0)]], +]; + +$manager = new MongoDB\Driver\Manager(URI, [], ['autoEncryption' => $autoEncryptionOpts, 'disableClientPersistence' => true]); + +$bulk = new MongoDB\Driver\BulkWrite(); +$bulk->insert(['x' => 1]); +$bulk->insert(['x' => 2]); +$bulk->insert(['x' => 3]); +$keyVaultClient->executeBulkWrite(NS, $bulk); + +MongoDB\Driver\Monitoring\addSubscriber(new CommandLogger); + +$query = new MongoDB\Driver\Query([], ['batchSize' => 2]); +$cursor = $keyVaultClient->executeQuery(NS, $query); + +$childPid = pcntl_fork(); + +if ($childPid === 0) { + /* Executing any operation with the parent's client resets this client as well as + * the keyVaultClient. Continuing iteration of the cursor opened on the + * keyVaultClient before resetting it should then result in an error due to + * the client having been reset. */ + $manager->executeCommand(DATABASE_NAME, new MongoDB\Driver\Command(['ping' => 1])); + + echo throws( + function () use ($cursor) { iterator_count($cursor); }, + MongoDB\Driver\Exception\RuntimeException::class + ), "\n"; + + echo "Child exits\n"; + exit; +} + +if ($childPid > 0) { + $waitPid = pcntl_waitpid($childPid, $status); + + if ($waitPid === $childPid) { + echo "Parent waited for child to exit\n"; + } + + unset($cursor); +} + +?> +===DONE=== + +--EXPECT-- +Parent executes find with batchSize: 2 +Child executes ping +OK: Got MongoDB\Driver\Exception\RuntimeException +Cannot advance cursor after client reset +Child exits +Parent waited for child to exit +Parent executes killCursors +===DONE===