[CDRIVER-2857] Provide a reset method to be called on clients after forking Created: 16/Oct/18  Updated: 28/Oct/23  Resolved: 04/Jan/19

Status: Closed
Project: C Driver
Component/s: libmongoc
Affects Version/s: None
Fix Version/s: 1.14.0

Type: Task Priority: Major - P3
Reporter: Rathi Gnanasekaran Assignee: Samantha Ritter (Inactive)
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
is depended on by CXX-1672 Driver session pools must be cleared ... Closed
is depended on by DRIVERS-578 Driver session pools must be cleared ... Closed
is depended on by PHPC-1274 Reset libmongoc client after forking ... Closed
is depended on by PHPC-1284 Driver session pools must be cleared ... Closed
Related
related to CDRIVER-3116 Do not disconnect sockets in mongoc_c... Closed
related to CDRIVER-3438 Destroy exhaust cursor socket in mong... Closed
related to CDRIVER-2919 Update documentation for mongoc_clien... Closed
related to CDRIVER-2918 Clean up topology background thread l... Closed
Epic Link: FY2019Q4 Quick Wins (C and CXX)

 Description   

When user code forks, various resources in the client need to be protected against parallel use in both the parent and the child code.  These include the following:

sessions:

  • ensure we don't call endSessions for lsids the parent process might be using
  • ensure we don't use such lsids at all, for any operations, in the child

cursors:

  • ensure we don't call killCursors for cursors the parent process might be using
  • ensure we don't call getmores on such cursors, either

connections:

  • close all client connections in the child, so we don't write to the same sockets as the parent

 

See DRIVERS-578 for more details.



 Comments   
Comment by Samantha Ritter (Inactive) [ 04/Jan/19 ]

After some discussion, we have decided not to implement a reset method for pooled clients. We cannot imagine a likely usage scenario for users who have a pooled client in multithreaded applications, and are still choosing to fork(). This article has convinced us that fork()ing in multithreaded programs is dangerous, and that we should not support it.

Closing this ticket as 'Fixed', since the single client reset method was implemented.

Comment by Githook User [ 07/Dec/18 ]

Author:

{'name': 'samantharitter', 'email': 'samantha.ritter@10gen.com', 'username': 'samantharitter'}

Message: CDRIVER-2857 Implement mongoc_client_reset
Branch: master
https://github.com/mongodb/mongo-c-driver/commit/500f49c580f4de339d850bb6d83c02afedbdf33d

Comment by Jeremy Mikola [ 16/Nov/18 ]

jesse: I've re-purposed PHPC-1274 to use that for tracking PHP's integration of mongoc_client_reset() and have revised its description accordingly (in sync with Sam's updates here). We will definitely detect PID changes to avoid calling mongoc_client_reset() more times than is absolutely necessary.

Comment by A. Jesse Jiryu Davis [ 16/Nov/18 ]

I think the right logic for the PHP driver is to cache a PID on a PHP-level client object when the client is created. Whenever it creates / destroys a session or cursor with a client, it should check if the current PID is the same as it was the last time it created / destroyed a session or cursor with the same client. If the PID is different, the PHP driver updates the PID cached on the client, and then calls mongoc_client_reset, and then proceeds to create / destroy the session or cursor.

 

Consider some sequences:

scenario 1
PHP-level client_pid = PARENT
create cursor A
fork 
in child:
create cursor B
   set PHP-level client_pid = CHILD (PHP logic)
   call client_reset in child (PHP logic)
destroy cursor A
   mongoc_cursor_destroy
   client's reset counter is greater, do nothing (C logic)
destroy cursor B
   mongoc_cursor_destroy
   its reset counter is current, send killCursors (C logic)
 
scenario 2
PHP-level client_pid = PARENT
create cursor A
fork 
in child:
destroy cursor A
   set PHP-level client_pid = CHILD (PHP logic)
   call client_reset in child (PHP logic)
   mongoc_cursor_destroy
   pid changed! do nothing (C logic)
destroy cursor B
   mongoc_cursor_destroy
   its reset counter is current, send killCursors (C logic)
 
 
scenario 3
PHP-level client_pid = PARENT
create session A
fork 
in child:
create session B
	call client_reset in child, C logic clears the session pool (empty in this scenario)
        mongoc_client_start_session
destroy session A
   mongoc_client_session_destroy
   pid changed! do nothing (C logic)
destroy session B
   mongoc_client_session_destroy
   its reset counter is current, push its server session to pool (C logic)

Comment by Kevin Albertson [ 25/Oct/18 ]

Similar to PERL-1012, let's create a function like mongoc_client_reset/mongoc_client_pool_reset which users can call after forking. This would clear the session pool without sending endSessions.

This could also potentially solve the issue described in PHPC-1274. E.g. by keeping a monotonic counter that is incremented on every call to the reset function. Then the cursor can omit sending killCursors if it detects it has been called after a reset.

Generated at Wed Feb 07 21:16:33 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.