-
Type:
Bug
-
Resolution: Done
-
Priority:
Critical - P2
-
Affects Version/s: 1.1.8
-
Component/s: None
-
None
-
Environment:PHP 5.5.37 (possible other PHP 5.x, but not PHP 7)
-
None
-
None
-
None
-
None
-
None
-
None
-
None
jwage encountered a crash due to a libmongoc assert failure, where a cursor was being killed during a shutdown function:
#0 0x0000003b20e32625 in raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
resultvar = 0
pid = <value optimized out>
selftid = <value optimized out>
#1 0x0000003b20e33e05 in abort () at abort.c:92
save_stage = 2
act = {__sigaction_handler = {sa_handler = 0x60, sa_sigaction = 0x60}, sa_mask = {__val = {253958350976, 47549832, 47537728, 0, 140735799216256, 1, 253955669547, 206158430256, 140735799214840,
140735799214624, 157312, 70326552, 228518431, 32, 140250760109120, 1454}}, sa_flags = -1396939744, sa_restorer = 0x10}
sigs = {__val = {32, 0 <repeats 15 times>}}
#2 0x00007f8eacb9e415 in mongoc_cluster_fetch_stream_pooled (cluster=0x2d58d88, sd=0x3e2c1d0, reconnect_ok=false, error=0x0) at src/mongoc/mongoc-cluster.c:1544
stream = 0x7fff9b51c880
topology = <value optimized out>
cluster_node = <value optimized out>
timestamp = <value optimized out>
#3 _mongoc_cluster_stream_for_server_description (cluster=0x2d58d88, sd=0x3e2c1d0, reconnect_ok=false, error=0x0) at src/mongoc/mongoc-cluster.c:1365
topology = <value optimized out>
server_stream = <value optimized out>
#4 0x00007f8eacb9e838 in mongoc_cluster_stream_for_server (cluster=0x2d58d88, server_id=3, reconnect_ok=false, error=0x0) at src/mongoc/mongoc-cluster.c:1422
topology = <value optimized out>
sd = 0x3e2c1d0
server_stream = 0x0
__func__ = "mongoc_cluster_stream_for_server"
#5 0x00007f8eacb991a6 in _mongoc_client_kill_cursor (client=0x2d58d70, server_id=<value optimized out>, cursor_id=4536838857318534913, db=0x7fff9b51c880 "opensky_devo", collection=0x3e4b9a5 "sellables")
at src/mongoc/mongoc-client.c:1282
server_stream = <value optimized out>
__func__ = "_mongoc_client_kill_cursor"
#6 0x00007f8eacba5028 in _mongoc_cursor_destroy (cursor=0x3e4b7f0) at src/mongoc/mongoc-cursor.c:273
db = "opensky_devo\000\000\000\000 -\321\003\000\000\000\000p\022\315\003\000\000\000\000X\000\000\000\000\000\000\000bM[\000\000\000\000\000\270\v\000\000\000\000\000\000bM[\000\000\000\000\000\220\017\000\000\000\000\000\000bM[\000\000\000\000\000 [\345\003\000\000\000\000\020Y\344\003\000\000\000\000@\002\000\000\000\000\000\000bM[\000\000\000\000\000X\000\000\000\000\000\000\000bM[\000\000\000\000"
__func__ = "_mongoc_cursor_destroy"
#7 0x00007f8eacdf67b2 in php_phongo_cursor_free (cursor=0x3e09b60) at /usr/src/debug/php-pecl-mongodb-1.1.8/NTS/php_phongo.c:2142
No locals.
#8 0x00007f8eacdedbe1 in php_phongo_cursor_free_object (object=<value optimized out>) at /usr/src/debug/php-pecl-mongodb-1.1.8/NTS/src/MongoDB/Cursor.c:226
intern = 0x3e09b60
#9 0x000000000060623c in zend_objects_store_free_object_storage (objects=0x9f66c0) at /usr/src/debug/php-5.5.37/Zend/zend_objects_API.c:97
obj = <value optimized out>
i = <value optimized out>
#10 0x00000000005ceb23 in shutdown_executor () at /usr/src/debug/php-5.5.37/Zend/zend_execute_API.c:290
---Type <return> to continue, or q <return> to quit---
__orig_bailout = 0x7fff9b51ce80
__bailout = {{__jmpbuf = {10445600, -9101158388112889313, 140251056034432, 140251056037176, 140251056037720, 0, 9100937786234956319, -9101158395108857313}, __mask_was_saved = 0, __saved_mask = {
__val = {9345585548714895903, 0, 5983586, 32, 5983586, 184, 5983586, 140251056282616, 62546720, 96, 10445336, 1, 140251056034432, 140251056037176, 6139470, 10445248}}}}
#11 0x00000000005dcce2 in zend_deactivate () at /usr/src/debug/php-5.5.37/Zend/zend.c:946
No locals.
#12 0x000000000057c761 in php_request_shutdown (dummy=<value optimized out>) at /usr/src/debug/php-5.5.37/main/main.c:1813
report_memleaks = 1 '\001'
#13 0x00000000006976c9 in main (argc=<value optimized out>, argv=<value optimized out>) at /usr/src/debug/php-5.5.37/sapi/fpm/fpm/fpm_main.c:1981
primary_script = <value optimized out>
__orig_bailout = 0x0
__bailout = {{__jmpbuf = {0, 9100937787569793567, 2, 0, 10423264, 0, 9100937786052504095, -9101158278872241633}, __mask_was_saved = 0, __saved_mask = {__val = {0 <repeats 14 times>, 253950458591,
0}}}}
exit_status = 0
c = <value optimized out>
use_extended_info = 0
file_handle = {type = ZEND_HANDLE_FILENAME, filename = 0x7f8ebe5fd0b8 "x\324\177\002", opened_path = 0x0, handle = {fd = 0, fp = 0x0, stream = {handle = 0x0, isatty = 0, mmap = {len = 0,
pos = 253979787264, map = 0x3b2261d000, buf = 0x3b2261c6bc <Address 0x3b2261c6bc out of bounds>, old_handle = 0x3b2261c6bc, old_closer = 0}, reader = 0x5, fsizer = 0x3b2281c000,
closer = 0x3b2281e000}}, free_filename = 0 '\000'}
orig_optind = 1
orig_optarg = 0x0
ini_entries_len = <value optimized out>
max_requests = 2500
requests = 11
fcgi_fd = 10444256
request = {listen_socket = 0, fd = -1, id = 1, keep = 0, closed = 0, in_len = 0, in_pad = 7, out_hdr = 0x0, out_pos = 0x7fff9b51d010 "\001\006",
out_buf = "\001\006\000\001\000\a\001\000/html>\n\000\001\003\000\001\000\b\000\000\000\000\000\000\000he\r\nDate: Fri, 08 Jul 2016 15:24:14 GMT\r\nContent-Type: text/html; charset=UTF-8\r\nX-OSKY-P-NODE: dc1osphp01\r\n\r\n\000\000\000\000\000\001\006\000\001\330p\000\000ssion-language/Symfony/Component/ExpressionLangua"..., reserved = '\000' <repeats 15 times>, env = 0x7f8ebe5fd040}
fpm_config = 0x0
fpm_prefix = 0x0
fpm_pid = 0x0
test_conf = 0
force_daemon = 1
php_information = 0
php_allow_to_run_as_root = 0
__func__ = "main"
My initial analysis:
Also of note: before I noticed mongoc_cluster_fetch_stream_pooled() in the crash backtrace, we originally suspected this was a recurrence of
PHPC-671(fixed in 1.1.7), which entailed a crash due to PHP 5.x freeing the MongoDB\Driver\Manager object before open MongoDB\Driver\Cursor objects. That resulted in the Manager also destroying libmongoc's client object (and all streams) and causing a use-after-free when the Cursor wanted to free itself and send a kill command over the stream it was last associated with.That said, mongoc_cluster_fetch_stream_pooled() is really the red flag here, as there's no reason that libmongoc should not be in single_threaded mode. See the _mongoc_cluster_stream_for_server_description for the relevant logic in libmongoc (one level deep in the backtrace).
Most likely, the MongoDB\Driver\Manager (and its mongoc_client_t) was again freed before the non-exhausted MongoDB\Driver\Cursor. This resulted in topology->single_threaded being zeroed in memory (responsible for libmongoc attempting to fetch a stream from a pool). Somehow, the mongoc_cursor_t still had a reference to this memory when it attempted to kill itself.
Since jwage was using mongo-php-adapter, this issue may be a duplicate of PHPC-732 and caused entirely by the use of generators. We'll need to confirm that.