Skip to content

Commit b55ea81

Browse files
committed
PHPC-913: Child process should not re-use mongoc_client_t objects from parent
1 parent ab2e2b8 commit b55ea81

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

php_phongo.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@
4141
# include <ext/standard/php_smart_str.h>
4242
#endif
4343

44+
/* getpid() */
45+
#if HAVE_UNISTD_H
46+
# include <unistd.h>
47+
#endif
48+
#ifdef PHP_WIN32
49+
# include <process.h>
50+
#endif
51+
4452
/* Stream wrapper */
4553
#include <main/php_streams.h>
4654
#include <main/php_network.h>
@@ -1403,7 +1411,8 @@ static char *php_phongo_manager_make_client_hash(const char *uri_string, zval *o
14031411
#if PHP_VERSION_ID >= 70000
14041412
zval args;
14051413

1406-
array_init_size(&args, 3);
1414+
array_init_size(&args, 4);
1415+
ADD_ASSOC_LONG_EX(&args, "pid", getpid());
14071416
ADD_ASSOC_STRING(&args, "uri", uri_string);
14081417

14091418
if (options) {
@@ -1434,7 +1443,8 @@ static char *php_phongo_manager_make_client_hash(const char *uri_string, zval *o
14341443
zval *args;
14351444

14361445
MAKE_STD_ZVAL(args);
1437-
array_init_size(args, 3);
1446+
array_init_size(args, 4);
1447+
ADD_ASSOC_LONG_EX(args, "pid", getpid());
14381448
ADD_ASSOC_STRING(args, "uri", uri_string);
14391449

14401450
if (options) {

tests/manager/bug0913-001.phpt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
--TEST--
2+
PHPC-913: Child process should not re-use mongoc_client_t objects from parent
3+
--SKIPIF--
4+
<?php if (!function_exists('pcntl_fork')) { die('skip pcntl_fork() not available'); } ?>
5+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; CLEANUP(STANDALONE); SLOW(); ?>
6+
--FILE--
7+
<?php
8+
require_once __DIR__ . "/../utils/basic.inc";
9+
10+
function logMyURI(MongoDB\Driver\Manager $manager)
11+
{
12+
$command = new MongoDB\Driver\Command(['whatsmyuri' => 1]);
13+
$cursor = $manager->executeCommand(DATABASE_NAME, $command);
14+
$uri = $cursor->toArray()[0]->you;
15+
16+
$bulk = new MongoDB\Driver\BulkWrite();
17+
$bulk->insert(['pid' => getmypid(), 'uri' => $uri]);
18+
$manager->executeBulkWrite(NS, $bulk);
19+
}
20+
21+
$manager = new MongoDB\Driver\Manager(STANDALONE);
22+
logMyURI($manager);
23+
24+
$parentPid = getmypid();
25+
$childPid = pcntl_fork();
26+
27+
if ($childPid === 0) {
28+
$manager = new MongoDB\Driver\Manager(STANDALONE);
29+
logMyURI($manager);
30+
31+
/* Due to PHPC-912, we cannot allow the child process to terminate before
32+
* the parent is done using its client, lest it destroy the mongoc_client_t
33+
* object and shutdown its socket(s). Sleep for 250ms to allow the parent
34+
* time to query for our logged URI. */
35+
usleep(250000);
36+
exit;
37+
}
38+
39+
if ($childPid) {
40+
/* Sleep for 100ms to allow the child time to log its URI. Ideally, we would
41+
* wait for the child to finish, but PHPC-912 prevents us from doing so. */
42+
usleep(100000);
43+
44+
$cursor = $manager->executeQuery(NS, new MongoDB\Driver\Query([]));
45+
$results = $cursor->toArray();
46+
47+
printf("%d connections were logged\n", count($results));
48+
printf("PIDs differ: %s\n", $results[0]->pid !== $results[1]->pid ? 'yes' : 'no');
49+
printf("URIs differ: %s\n", $results[0]->uri !== $results[1]->uri ? 'yes' : 'no');
50+
51+
$waitPid = pcntl_waitpid($childPid, $status);
52+
53+
if ($waitPid > 0) {
54+
printf("Parent(%d) waited for child(%d) to exit\n", $parentPid, $waitPid);
55+
}
56+
}
57+
58+
?>
59+
===DONE===
60+
<?php exit(0); ?>
61+
--EXPECTF--
62+
2 connections were logged
63+
PIDs differ: yes
64+
URIs differ: yes
65+
Parent(%d) waited for child(%d) to exit
66+
===DONE===

0 commit comments

Comments
 (0)