PHP-FPM processes holding onto MongoDB connection states-Collection of common programming errors

For the relevant part of our server stack, we’re running:

  • NGINX 1.2.3
  • PHP-FPM 5.3.10 with PECL mongo 1.2.12
  • MongoDB 2.0.7
  • CentOS 6.2

We’re getting some strange, but predictable behavior when the MongoDB server goes away (crashes, gets killed, etc). Even with a try/catch block around the connection code, i.e:

try
{
    $mdb = new Mongo('mongodb://localhost:27017');
}
catch (MongoConnectionException $e)
{
    die( $e->getMessage() );
}

$db = $mdb->selectDB('collection_name');

Depending on which PHP-FPM workers have connected to mongo already, the connection state is cached, causing further exceptions to go unhandled, because the $mdb connection handler can’t be used. The troubling thing is that the try does not consistently fail for a considerable amount of time, up to 15 minutes later, when — I assume — the php-fpm processes die/respawn.

Essentially, the behavior is that when you hit a worker that hasn’t connected to mongo yet, you get the die message above, and when you connect to a worker that has, you get an unhandled exception from $mdb->selectDB('collection_name'); because catch does not run.

When PHP is a single process, i.e. via Apache with mod_php, this behavior does not occur. Just for posterity, going back to Apache/mod_php is not an option for us at this time.

Is there a way to fix this behavior? I don’t want the connection state to be inconsistent between different php-fpm processes.

Edit: While I wait for the driver to be fixed in this regard, my current workaround is to do a quick polling to determine if the driver can handle requests and then load or not load the MongoDB library/run queries if it can’t connect/query:

try
{
    // connect
    $mongo = new Mongo("mongodb://localhost:27017");

    // try to do anything with connection handle
    try
    {
        $mongo->YOUR_DB->YOUR_COLLECTION->findOne();
        $mongo->close();
        define('MONGO_STATE', TRUE);
    }
    catch(MongoCursorException $e)
    {
        $mongo->close();
        error_log('Error connecting to MongoDB: ' . $e->getMessage() );
        define('MONGO_STATE', FALSE);
    }
}
catch(MongoConnectionException $e)
{
    error_log('Error connecting to MongoDB: ' . $e->getMessage() );
    define('MONGO_STATE', FALSE);
}