ExportXMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 2.5.6
    • Affects Version/s: 2.5.5
    • Component/s: None
    • None
    • 2
    • None
    • PHP Drivers
    • Not Needed
    • None
    • None
    • None
    • None
    • None
    • None

      Track GitHub Issue: https://github.com/mongodb/mongo-php-driver/issues/2199 

       


      Summary

      When the extension runs inside FrankenPHP (ZTS, worker mode) 1.13.x, the process aborts after FrankenPHP reboots its PHP threads:
      mongoc-handshake.c:904 mongoc_handshake_data_append(): assertion failed: gMongocHandshake.platform
       
      FrankenPHP 1.13.0 (php/frankenphp#2364) reboots all PHP threads when a file watched by watch changes, or when opcache_reset() is called. The reboot tears the engine down and starts it again inside the same OS process (php_module_shutdown() + tsrm_shutdown(), then startup again).

      What I think happens

      1. On reboot, every thread runs GSHUTDOWN. The last one brings phongo_num_threads to 0 and calls mongoc_cleanup() (phongo.c, PHP_GSHUTDOWN_FUNCTION). _mongoc_handshake_cleanup() frees the handshake globals.
      2. MINIT runs again and calls mongoc_init(). In libmongoc 2.5.6, mongoc_init() and mongoc_cleanup() are guarded by bson_once (mongoc-init.c, lines 161-162 and 207-208). The second mongoc_init() in the same process is a no-op, so _mongoc_handshake_init() never runs again.
      3. The next new MongoDB\Client() / MongoDB\Driver\Manager reaches mongoc_handshake_data_append(), finds gMongocHandshake.platform unset, and the assertion aborts the whole server.

      The comment above phongo_num_threads assumes the last GSHUTDOWN means process end. That no longer holds when the SAPI restarts the engine in-process.

      Environment

      • ext-mongodb 2.5.5 (bundled libmongoc / libbson 2.5.6, libmongocrypt 1.20.5)
      • PHP 8.5.12 ZTS
      • FrankenPHP 1.13.2 (Caddy 2.11.7), worker mode, Debian-based official image, extension installed with install-php-extensions mongodb
      • The client is created lazily inside the worker on the first request that needs it (a Monolog handler)

      Evidence

      In a development container with watch enabled, we saw 19 thread reboots over 20k log lines. Each of the 7 assertions came right after a rebooting all PHP threads line, and the container restarted 32 times. Production (no watch, no opcache_reset()) is not affected. I have not reduced it to a minimal standalone script yet. The expected minimal repro is a FrankenPHP worker with watch that creates a MongoDB\Driver\Manager and runs a command per request, then a touch of a watched file and one more request.

      Question

      Is restarting the engine in-process (MSHUTDOWN/GSHUTDOWN followed by MINIT in the same process) something the extension can support? For example, skip mongoc_cleanup() under ZTS and leave it to process exit, or re-run the handshake init on MINIT. Or should this be handled on the FrankenPHP side? I am happy to open a matching issue there.

            Assignee:
            Jérôme Tamarelle
            Reporter:
            Jérôme Tamarelle
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: