Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ modules
run-tests.php
tags
.lvimrc
mongocryptd.pid

# phpt leftovers
*.diff
Expand Down
5 changes: 5 additions & 0 deletions php_phongo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
105 changes: 105 additions & 0 deletions tests/cursor/bug1529-001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
--TEST--
PHPC-1529: Resetting a client should also reset the keyVaultClient
--SKIPIF--
<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
<?php skip_if_not_live(); ?>
<?php skip_if_not_clean(); ?>
<?php skip_if_server_version('<', '4.2'); ?>
<?php skip_if_not_libmongocrypt(); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

class CommandLogger implements MongoDB\Driver\Monitoring\CommandSubscriber
{
private $pid;

public function __construct()
{
$this->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===
<?php exit(0); ?>
--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===