New PHP MongoDb driver and parallel processes

Alex Tatulchenkov
2 min readJun 16, 2016

After refactoring described in my previous article I decided to check if still able to use mongo in parallel processes using pcntl_fork().

So I ran my code responsible for handling several items from the queue in parallel processes (This code was using very useful lib WorkerPool) and got this:

MongoDB\Driver\Exception\RuntimeException: Invalid response_to for query. Expected 23, got 22.

It’s looks like Mongo tries to respond to different process not one was asking for data. Looks strange and I decided to google it by “Invalid response_to for query” and got 2 (yes only two) results and both of them were links to Mongo driver source code on github.

After this I was trying to reconnect to MongoDb in child processes, use semaphore and refactor some code to be sure that my code works as expected. But I was getting the same error again and again. Behavior of the script was strange:

  • in 70% it ended with the error mentioned above
  • in 20% it worked as expected
  • in 10% it was hanging

I tried the same code with old MongoDb driver and it worked. The only difference that my old driver for php 5.5 was talking to MongoDb 3.2 and new driver for php 7.0 was talking to MongoDb 2.6 so I upgraded latter on my VM. And … Nothing

It became clear that the issue is in new driver. And I continued to google.

Finally I found opened bug for php driver.

When using pcntl_fork() with the new MongoDB\Driver it is impossible to create a new MongoDB manager in the child process if one has been opened in the parent process. The newly created one in the child process seem to share a socket to MongoDB and throw errors based on receiving each others responses.

The source of problem is that driver includes the URI string ( MongoDB\Driver\Manager’s first argument) in its hash for persistent sockets. So if you use the same URI in child processes you will get the same socket.

As a work around I decided to add pid of current process to URI in child processes so I’ll be sure I get new hash and new socket in each process:

$manager = new \MongoDB\Driver\Manager(“mongodb://localhost:27017/?x=” . posix_getpid());

This work around fixed mentioned issue but also I realized that I have some places in the code that have to be refactored…

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Alex Tatulchenkov
Alex Tatulchenkov

Written by Alex Tatulchenkov

Senior Software Engineer at Intetics Inc., AppSec Manifesto evangelist

Responses (2)

Write a response

I user apache prefork MPM, no threads or process fork in my PHP application.But this problem still occured, Any suggestion? Thank you!

--

Thanks very mach man , I am looking for this solution since 2 day
Great work

--