Skip to content

Commit 0ea1c5e

Browse files
committed
PHPC-231: Manager instances should not free streams that are still in use
1 parent d294b60 commit 0ea1c5e

File tree

2 files changed

+60
-7
lines changed

2 files changed

+60
-7
lines changed

php_phongo.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,22 @@ void phongo_stream_destroy(mongoc_stream_t *stream_wrap) /* {{{ */
656656
{
657657
php_phongo_stream_socket *base_stream = (php_phongo_stream_socket *)stream_wrap;
658658

659+
mongoc_log(MONGOC_LOG_LEVEL_DEBUG, MONGOC_LOG_DOMAIN, "Not destroying RSRC#%d", base_stream->stream->rsrc_id);
660+
/*
661+
* DON'T DO ANYTHING TO THE INTERNAL base_stream->stream
662+
* The stream should not be closed during normal dtor -- as we want it to
663+
* survive until next request.
664+
* We only clean it up on failure and (implicitly) MSHUTDOWN
665+
*/
666+
667+
efree(base_stream);
668+
} /* }}} */
669+
void phongo_stream_failed(mongoc_stream_t *stream_wrap) /* {{{ */
670+
{
671+
php_phongo_stream_socket *base_stream = (php_phongo_stream_socket *)stream_wrap;
672+
659673
if (base_stream->stream) {
674+
mongoc_log(MONGOC_LOG_LEVEL_DEBUG, MONGOC_LOG_DOMAIN, "Destroying RSRC#%d", base_stream->stream->rsrc_id);
660675
TSRMLS_FETCH_FROM_CTX(base_stream->tsrm_ls);
661676

662677
php_stream_free(base_stream->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
@@ -666,8 +681,12 @@ void phongo_stream_destroy(mongoc_stream_t *stream_wrap) /* {{{ */
666681
efree(base_stream);
667682
} /* }}} */
668683

669-
int phongo_stream_close(mongoc_stream_t *stream) /* {{{ */
684+
int phongo_stream_close(mongoc_stream_t *stream_wrap) /* {{{ */
670685
{
686+
php_phongo_stream_socket *base_stream = (php_phongo_stream_socket *)stream_wrap;
687+
688+
mongoc_log(MONGOC_LOG_LEVEL_DEBUG, MONGOC_LOG_DOMAIN, "Closing RSRC#%d", base_stream->stream->rsrc_id);
689+
phongo_stream_destroy(stream_wrap);
671690
return 0;
672691
} /* }}} */
673692

@@ -938,28 +957,30 @@ mongoc_stream_t* phongo_stream_initiator(const mongoc_uri_t *uri, const mongoc_h
938957
}
939958

940959
spprintf(&uniqid, 0, "mongodb://%s:%s@%s:%d/%s?ssl=%d&authMechanism=%s&authSource=%s",
941-
mongoc_uri_get_username(uri),
942-
mongoc_uri_get_password(uri),
960+
mongoc_uri_get_username(uri) ?: "",
961+
mongoc_uri_get_password(uri) ?: "",
943962
host->host,
944963
host->port,
945-
mongoc_uri_get_database(uri),
964+
mongoc_uri_get_database(uri) ?: "",
946965
mongoc_uri_get_ssl(uri) ? 1 : 0,
947-
mongoc_uri_get_auth_mechanism(uri),
948-
mongoc_uri_get_auth_source(uri)
966+
mongoc_uri_get_auth_mechanism(uri) ?: "",
967+
mongoc_uri_get_auth_source(uri) ?: ""
949968
);
950969

951970
mongoc_log(MONGOC_LOG_LEVEL_DEBUG, MONGOC_LOG_DOMAIN, "Connecting to '%s'", uniqid);
952971
stream = php_stream_xport_create(dsn, dsn_len, 0, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT | STREAM_XPORT_CONNECT_ASYNC, uniqid, timeoutp, (php_stream_context *)user_data, &errmsg, &errcode);
953972

954-
efree(uniqid);
955973
if (!stream) {
956974
bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_CONNECT, "Failed connecting to '%s:%d': %s", host->host, host->port, errmsg);
957975
efree(dsn);
976+
efree(uniqid);
958977
if (errmsg) {
959978
efree(errmsg);
960979
}
961980
RETURN(NULL);
962981
}
982+
mongoc_log(MONGOC_LOG_LEVEL_DEBUG, MONGOC_LOG_DOMAIN, "Created: RSRC#%d as '%s'", stream->rsrc_id, uniqid);
983+
efree(uniqid);
963984

964985
/* Avoid invalid leak warning in debug mode when freeing the stream */
965986
#if ZEND_DEBUG
@@ -1021,6 +1042,7 @@ mongoc_stream_t* phongo_stream_initiator(const mongoc_uri_t *uri, const mongoc_h
10211042
/* flush missing, doesn't seem to be used */
10221043
base_stream->vtable.type = 100;
10231044
base_stream->vtable.destroy = phongo_stream_destroy;
1045+
base_stream->vtable.failed = phongo_stream_failed;
10241046
base_stream->vtable.close = phongo_stream_close;
10251047
base_stream->vtable.writev = phongo_stream_writev;
10261048
base_stream->vtable.readv = phongo_stream_readv;

tests/standalone/bug0231.phpt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Multiple managers sharing streams: Using stream after closing manager
3+
--SKIPIF--
4+
<?php require __DIR__ . "/../utils/basic-skipif.inc"; CLEANUP(STANDALONE)?>
5+
--FILE--
6+
<?php
7+
require_once __DIR__ . "/../utils/basic.inc";
8+
9+
$manager = new MongoDB\Driver\Manager(STANDALONE);
10+
$manager2 = new MongoDB\Driver\Manager(STANDALONE);
11+
12+
13+
$listdatabases = new MongoDB\Driver\Command(array("listDatabases" => 1));
14+
$retval = $manager->executeCommand("admin", $listdatabases);
15+
$retval = $manager2->executeCommand("admin", $listdatabases);
16+
17+
foreach($retval as $database) {
18+
}
19+
20+
$manager = null;
21+
$retval = $manager2->executeCommand("admin", $listdatabases);
22+
23+
foreach($retval as $database) {
24+
}
25+
echo "All Good!\n";
26+
?>
27+
===DONE===
28+
<?php exit(0); ?>
29+
--EXPECT--
30+
All Good!
31+
===DONE===

0 commit comments

Comments
 (0)