Uploaded image for project: 'C Driver'
  1. C Driver
  2. CDRIVER-2100

SegFault in 1.6.1 when 'dispose cursor' after doing a find on a $or or $and query

    • Type: Icon: Bug Bug
    • Resolution: Cannot Reproduce
    • Priority: Icon: Critical - P2 Critical - P2
    • 1.6.1
    • Affects Version/s: 1.6.1
    • Component/s: libbson, libmongoc
    • Labels:
    • Environment:
      Linux, CentOS

      I'm experiencing a segfault, whenever I do a query which involves a $or or $and.

      If I do a 'count()', then it's returning the correct number of records, but when I do a 'find', then I get a segfault when attempting to dispose the returned cursor. LastError returns NoError.

      Sample logging;
      -------------------------
      nitialising Mongo
      Mongo Version: 1.6.1
      mongoc_cursor_destroy: 0
      mongoc_collection_destroy: 0
      mongoc_client_destroy: 0
      Connect Query: { "$or" : [

      { "token" : "58af74c34d94887d0b8b4861" }

      ,

      { "token" : "ALL" }

      ] }
      Doing mongo.find()
      Mongo Error: No Error
      mongo.find() success: 20480 records
      Finished Mongo Find
      Disconnect Mongo Connection
      mongoc_cursor_destroy: 1
      2017-03-27 08:03:45 PM: SIGSEGV - Fatal !
      [Dispatch Backtrace]: (1) ./dispatch_service(_Z14signal_handleri+0x85) [0x4068cb]
      [Dispatch Backtrace]: (2) /lib64/libc.so.6(+0x35250) [0x7f1edb61a250]
      [Dispatch Backtrace]: (2) /lib64/libc.so.6(+0x35250) [0x7f1edb61a250]
      [Dispatch Backtrace]: (3) /lib64/libbson-1.0.so.0(bson_destroy+0x2c) [0x7f1edc1d5c3c]
      [Dispatch Backtrace]: (4) /lib64/libmongoc-1.0.so.0(+0x1bb65) [0x7f1edc415b65]
      [Dispatch Backtrace]: (5) ./dispatch_service(_ZN5Mongo10disconnectEv+0x88) [0x40b2ce]
      [Dispatch Backtrace]: (6) ./dispatch_service(_Z17initialMongoQueryv+0x1c5) [0x406bd8]
      [Dispatch Backtrace]: (7) ./dispatch_service(main+0xdb) [0x406d28]
      [Dispatch Backtrace]: (8) /lib64/libc.so.6(__libc_start_main+0xf5) [0x7f1edb606b35]
      [Dispatch Backtrace]: (9) ./dispatch_service() [0x4056c9]

      Below is the code aspect for form this query. If I do a simpler query: eg. { "sequence":

      { "$gt": 123456 }

      } then working as expected. It's only when I try something like: { "$or" : [ { or { "$and" : [ {

      The query is valid as far as I can tell - returning a 'count' of records in mongoc and also in MongoHub (for OS X)

      -------------------------------------------

      
      	Mongo mongo;
      	
      	mongo.connect("notification", "notifyqueue");
      	
      //			mongo.addQuery_Int32GT("sequence", 390000 ); //sequence );
      //	mongo.addQuery_Int32GTAndCharOrChar( "sequence", 300000, "token", "all", "token", "0bc1db8f5ce1873a528510c636d4ee6f" );
      	mongo.addQuery_CharOrChar( "token", "58af74c34d94887d0b8b4861", "token", "ALL" );
      
      	
      	printf( "Connect Query: %s\n", mongo.returnQuery().c_str() );
      	
      //	printf("mongo.find() success:  %d records\n", (int)mongo.count() );
      	
      	printf("Doing mongo.find()\n");
      	if( mongo.find() )
      	{
      		printf( "Mongo Error: %s\n", mongo.lastErrorMessage().c_str() );
      
      		printf("mongo.find() success:  %d records\n", (int)mongo.count() );
      		while( mongo.nextRecord() )
      //		{
      			printf("Mongo Next Record");
      //			std::string out = mongo.recordAsString();
      //			printf("Record: %s\n--------\n", out.c_str() );
      //		}
      		printf("Finished Mongo Find\n");
      
      	} else {
      		printf( "Mongo Error: %s\n", mongo.lastErrorMessage().c_str() );
      	}
      
      	printf("Disconnect Mongo Connection\n");
      	mongo.disconnect();
      
      

      Aspects of Mongo class that is called
      -------------------------------------------------------

      
      
      void Mongo::addQuery_CharOrChar( const char * fieldname1, const char * value1, const char * fieldname2, const char * value2 )
      {
      // eg.  { $or:[ {fieldname: value}, {fieldname: value} ] }
      	if( !query ) query = BSON_CREATE();
      	
      	bson_t child, child1, child2;
      
      	
      	if( BSON_APPEND_ARRAY_BEGIN( query, "$or", &child ) )
      	{
      		if( BSON_APPEND_DOCUMENT_BEGIN( &child, "", &child1 ) )
      		{
      			BSON_APPEND_UTF8 ( &child1, fieldname1, value1);
      			bson_append_document_end( &child, &child1 );
      		}
      
      		if( BSON_APPEND_DOCUMENT_BEGIN( &child, "", &child2 ) )
      		{
      			BSON_APPEND_UTF8 ( &child2, fieldname2, value2);
      			bson_append_document_end( &child, &child2 );
      		}
      
      		bson_append_array_end( query, &child );
      	}
      
      }
      
      
      
      
      void Mongo::disconnect( void )
      {
      	try {
      		doc = NULL;
      		opts = BSON_DESTROY(opts);
      		query = BSON_DESTROY(query);
      
      		printf("mongoc_cursor_destroy: %d\n", (int)(cursor != NULL) );
      		if( cursor ) 		mongoc_cursor_destroy (cursor);				cursor = NULL;
      
      		printf("mongoc_collection_destroy: %d\n", (int)(collection != NULL) );
      		if( collection )	mongoc_collection_destroy (collection);		collection = NULL;
      		
      		printf("mongoc_client_destroy: %d\n", (int)(client != NULL) );
      		if( client )		mongoc_client_destroy (client);				client = NULL;
      		
      		
      		
      	} catch (...) {
      		log_write("Mongo::disconnect try...catch error");
      	}
      }
      
      void Mongo::connect( const char * theDatabase, const char * theCollection )
      {
      	try {
      		if( setup() )
      		{
      			// clean up if already connected to a different table / collection.
      			if( cursor ) 		mongoc_cursor_destroy (cursor);				cursor = NULL;
      			if( collection )	mongoc_collection_destroy (collection);		collection = NULL;
      			opts = BSON_DESTROY(opts);
      			query = BSON_DESTROY(query);
      			
      
      			// Connect to the new table
      			collection = mongoc_client_get_collection (client, theDatabase, theCollection );
      
      
      			// Initialise default options and query parameters
      //			opts = BSON_CREATE();
      //			query = BSON_CREATE();
      			doc = NULL;
      
      		}
      	} catch (...) {
      		log_write("Mongo::connect try...catch error");
      	}
      }
      
      
      
      bool Mongo::find( void )
      {
      	bool success = false;
      	
      	try {
      		if( !setup() )			return false;		// Not connected to Mongo Database
      		if( !collection )		return false;		// Haven't connected to database / collection
      	
      
      		if( cursor )		mongoc_cursor_destroy (cursor);
      	
      		if( !opts )			bson_init (opts);
      		if( !query )		bson_init (query);
      		doc = NULL;
      	
      		cursor = mongoc_collection_find_with_opts (collection, query, opts, read_prefs);
      		success = (cursor != NULL);
      		
      	} catch (...) {
      		log_write("Error: Mongo::find try...catch");
      	}
      	
      	return success;
      }
      
      uint64_t Mongo::count( void )
      {
      	uint64_t count = -1;
      	if( collection )
      	{
      		try {
      			count = mongoc_collection_count (collection, MONGOC_QUERY_SLAVE_OK, query, 0, 0, read_prefs, &error);
      		} catch(...) {
      			log_write("Error: Mongo::recordCount try...catch");
      		}
      	}
      	
      	return count;
      }
      

            Assignee:
            jesse@mongodb.com A. Jesse Jiryu Davis
            Reporter:
            kent@kamar.nz Kent Lendrum
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: