[CDRIVER-3685] Single-threaded mongoc_client_t in separate threads may write to the global handshake "frozen" boolean Created: 25/May/20  Updated: 10/Feb/23

Status: Backlog
Project: C Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Kevin Albertson Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Epic Link: CDRIVER-2733

 Description   

Discovered when investigatingĀ CDRIVER-3674. TSan reports a data race when creating multiple threads with single-threaded mongoc_client_t. Here is an example:

#include <mongoc/mongoc.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
 
void * threadfn (void* data) {
   bson_error_t error;
   mongoc_client_t *client = mongoc_client_new ("mongodb://localhost:27018 ");
   mongoc_collection_t *coll = mongoc_client_get_collection (client, "test", "test");
   bson_t *doc = bson_new();
   if (!mongoc_collection_insert_one (coll, doc, NULL, NULL, &error)) {
      printf ("thread: %s\n", error.message);
   }
   return NULL;
}
 
int
main (int argc, char *argv[])
{
   pthread_t threads[100];
   int i;
 
   mongoc_init ();
   for (i = 0; i < 100; i++) {
      pthread_create (threads + i, NULL, threadfn, NULL);
   }
   for (i = 0; i < 100; i++) {
      pthread_join (threads[i], NULL);
   }
   mongoc_cleanup();
}

Running with TSan shows this warning:

==================
WARNING: ThreadSanitizer: data race (pid=31598)
  Write of size 1 at 0x00010e16a128 by thread T4:
    #0 _mongoc_handshake_freeze mongoc-handshake.c:565 (libmongoc-1.0.0.dylib:x86_64+0x6560b)
    #1 _mongoc_topology_do_blocking_scan mongoc-topology.c:643 (libmongoc-1.0.0.dylib:x86_64+0xa3c68)
    #2 mongoc_topology_select_server_id mongoc-topology.c:879 (libmongoc-1.0.0.dylib:x86_64+0xa46fa)
    #3 _mongoc_cluster_select_server_id mongoc-cluster.c:2236 (libmongoc-1.0.0.dylib:x86_64+0x301ae)
    #4 _mongoc_cluster_stream_for_optype mongoc-cluster.c:2282 (libmongoc-1.0.0.dylib:x86_64+0x2a5ac)
    #5 mongoc_cluster_stream_for_writes mongoc-cluster.c:2368 (libmongoc-1.0.0.dylib:x86_64+0x2a6e7)
    #6 _mongoc_collection_write_command_execute_idl mongoc-collection.c:94 (libmongoc-1.0.0.dylib:x86_64+0x383e6)
    #7 mongoc_collection_insert_one mongoc-collection.c:1639 (libmongoc-1.0.0.dylib:x86_64+0x381c7)
    #8 threadfn example-client.c:16 (example-client:x86_64+0x100003ab4)
 
  Previous write of size 1 at 0x00010e16a128 by thread T2:
    #0 _mongoc_handshake_freeze mongoc-handshake.c:565 (libmongoc-1.0.0.dylib:x86_64+0x6560b)
    #1 _mongoc_topology_do_blocking_scan mongoc-topology.c:643 (libmongoc-1.0.0.dylib:x86_64+0xa3c68)
    #2 mongoc_topology_select_server_id mongoc-topology.c:879 (libmongoc-1.0.0.dylib:x86_64+0xa46fa)
    #3 _mongoc_cluster_select_server_id mongoc-cluster.c:2236 (libmongoc-1.0.0.dylib:x86_64+0x301ae)
    #4 _mongoc_cluster_stream_for_optype mongoc-cluster.c:2282 (libmongoc-1.0.0.dylib:x86_64+0x2a5ac)
    #5 mongoc_cluster_stream_for_writes mongoc-cluster.c:2368 (libmongoc-1.0.0.dylib:x86_64+0x2a6e7)
    #6 _mongoc_collection_write_command_execute_idl mongoc-collection.c:94 (libmongoc-1.0.0.dylib:x86_64+0x383e6)
    #7 mongoc_collection_insert_one mongoc-collection.c:1639 (libmongoc-1.0.0.dylib:x86_64+0x381c7)
    #8 threadfn example-client.c:16 (example-client:x86_64+0x100003ab4)
 
  Location is global 'gMongocHandshake' at 0x00010e16a0e0 (libmongoc-1.0.0.dylib+0x0000000ef128)
 
  Thread T4 (tid=13837519, running) created by main thread at:
    #0 pthread_create <null>:2668928 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x2aced)
    #1 main example-client.c:37 (example-client:x86_64+0x100003be9)
 
  Thread T2 (tid=13837517, finished) created by main thread at:
    #0 pthread_create <null>:2668928 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x2aced)
    #1 main example-client.c:37 (example-client:x86_64+0x100003be9)

I suspect it is unlikely this would amount to any observable bug, since both threads are writing "true" to frozen. And once the handshake is frozen it remains frozen indefinitely. But this is a signal that we may not have test coverage for multiple single threaded clients being used in multiple threads.


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