[CDRIVER-2100] SegFault in 1.6.1 when 'dispose cursor' after doing a find on a $or or $and query Created: 27/Mar/17  Updated: 28/Mar/17  Resolved: 28/Mar/17

Status: Closed
Project: C Driver
Component/s: libbson, libmongoc
Affects Version/s: 1.6.1
Fix Version/s: 1.6.1

Type: Bug Priority: Critical - P2
Reporter: Kent Lendrum Assignee: A. Jesse Jiryu Davis
Resolution: Cannot Reproduce Votes: 0
Labels: Bug, driver
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Linux, CentOS


Issue Links:
Duplicate
duplicates CDRIVER-2072 Using a filter or projection with emp... Closed

 Description   

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;
}



 Comments   
Comment by A. Jesse Jiryu Davis [ 28/Mar/17 ]

Thanks Kent, when I run similar code on my system, with empty strings as keys, I can't reproduce the crash.

Comment by Kent Lendrum [ 27/Mar/17 ]

Hi,

Sorry - I don't know the answer to that.

I'm using a mixture of C / C++ on a Linux Machine running latest version of CentOS.

In my project, I'm including:

#include <mongoc.h>
#include <bson.h>
#include <bcon.h>

I downloaded the 'mongo-c-driver-1.6.1.tar.gz

Unzipped, ./configure, make and finally make install.

I then compiled my project, pointing to the compiled projects.

during initialisation, I print the MONGOC_VERSION_S to console, and it reports 1.6.1
printf("Mongo Version: %s\n", MONGOC_VERSION_S );

Does this answer your question ?

Kent.

Comment by A. Jesse Jiryu Davis [ 27/Mar/17 ]

Thanks, was it CDRIVER-2072 that caused the crash?

Comment by Kent Lendrum [ 27/Mar/17 ]

Hi,

Okay - after submitting this request - I managed to resolve it.

This morning, I've played some more and have managed to track the issue down to the way I created the BSON Document.

So, I believe there are two issues here:

1) Using a bson_append_document_begin with a "" tag, causes the 'Find' to break.

2) After executing a 'find' with a Empty key in the BSON, the 'mongo_cursor_destroy' causes a 'SIGSEGV'

Let me know if you need more information.

thanks

Kent.

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

Then, when I do the 'Find', I get:

However - if I do this:

Then, when I do the Find, I get:

Interestingly - when I do a 'Count' - then I don't get an issue. It's only if I do a 'Find' that I then get the error.

After I received this error - if I then called 'mongoc_cursor_destroy' it would cause a 'SIGSEGV'

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

Comment by A. Jesse Jiryu Davis [ 27/Mar/17 ]

Hi, I'm not able to debug your C++ program, but if you can reproduce this bug using only C code and the C Driver then we can diagnose it.

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