[SERVER-10843] example tutorial (valgrind memleak checkable ) memory leak Created: 23/Sep/13  Updated: 10/Dec/14  Resolved: 11/Dec/13

Status: Closed
Project: Core Server
Component/s: Internal Client
Affects Version/s: 2.4.0
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: duanguoxue Assignee: Andrew Morrow (Inactive)
Resolution: Done Votes: 0
Labels: driver, memory-leak
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

CentOS release 6.4 (Final)


Attachments: File tutorial.cpp     Text File val2.4.6_no-show-reachable.log     Text File valgind_l_r.log     Text File valgind_l_r_2.4.6.log     Text File valgind_l_r_2.4.6_10-20.log     Text File valgind_master_11_16.log    
Issue Links:
Depends
depends on SERVER-7217 Provide a method for C++ driver clien... Closed
Operating System: Linux
Steps To Reproduce:

1 complile mongo-cxx-2.4 driver
2 valgrind --leak-check=full --show-reachable=yes --log-file=valgind_l_r.log ./tutorial

Participants:

 Description   

1 when tutotial exit,heap memleak.

2 some leak information.
==2254== HEAP SUMMARY:
==2254== in use at exit: 744 bytes in 19 blocks
==2254== total heap usage: 483 allocs, 464 frees, 137,635 bytes allocated

3 I have appended the valgrind detail information file.



 Comments   
Comment by Andrew Morrow (Inactive) [ 11/Dec/13 ]

I'm marking this as works as designed, since these are one-shot leaks and are intentional, for ow.

Comment by Andrew Morrow (Inactive) [ 23/Nov/13 ]

Hi guoxue.duan As I mentioned earlier in the thread, there are some allocations that we do not free related to the initialization of the library. Over time, we hope to reduce these. However, these leaks are one time only: they will not contribute to long term memory growth of the process, like a leak that was triggered on every invocation of the API.

Your best option is to add a valgrind suppression to ignore these errors.

Comment by duanguoxue [ 16/Nov/13 ]

execution script

valgrind  --leak-check=full  --log-file=valgind_master_11_16.log ./tutorial

Comment by duanguoxue [ 16/Nov/13 ]

Hi,
I've retested the shared library of the "mongoclient.so" ,test can well execute ,but still have memory leak related to the "GlobalInitializers".

I have track the master mongoclient code. We process the global "initializer" that is not very good.

    void ProcessInfo::initializeSystemInfo() {
        if (systemInfo == NULL) {
            systemInfo = new SystemInfo();
        }
    }

where and how to delete the new class objection. If delete the obj may generate a new race condition.
I attached my testing valgrind logfile "valgind_master_11_16.log"

Hope my testing can give some help for the issue.

mongo on branch of master
commit 9766387567e366e167835880818369cee7f8d42d

Comment by Andrew Morrow (Inactive) [ 06/Nov/13 ]

Hi guoxue.duan

I've reproduced your issue; thanks for bringing it to our attention. In the meantime, I think you can work around the problem by using the shared library version of the client driver, rather than the static library. If you add --sharedclient to your client driver build line, you should be able to link in exactly the same way but pick up the dynamic library and avoid this issue. Please let me know if that works for you while we look into resolving the issue in the static library.

Thanks,
Andrew

Comment by duanguoxue [ 06/Nov/13 ]

Thanks to you correct my error using "scans",but it accurately work for building "libmongoclient.a"(I read the SConstruct to guess how to using).

I have confirm to re-test my app using the below steps:

scons --use-system-boost --extrapath=/usr/local --full --prefix=$HOME/mongo-driver-install install-mongoclient

I also build the "mongo/client/example/tutorial.cpp" example app, but(my test and example tutorial.cpp) have the same error.

g++ -g tutorial.cpp -I/root/mongo-driver-install/include/ -pthread -lpthread -lboost_thread -lboost_filesystem -lboost_program_options -lboost_system -lmongoclient -o tutorial -L/root/mongo-driver-install/lib/

Error info:

failed to initialize the client driver: BadValue default

I hope you could try the mongo example "tutorial.cpp",you will be get answer.

mongo on branch master
commit c2d573d82da78c4bd897029670189e300f3f59ee

Comment by Andrew Morrow (Inactive) [ 05/Nov/13 ]

The --use-system-boost option does not take an argument, so I'm puzzled by how this is working for you to build. The proper argument to specify the search path for boost is --extrapath.

So your build line would look like:

scons --use-system-boost --extrapath=/usr/local

In addition, you probably want to install the client library and headers somewhere, then build your application. So if you were installing to $HOME/mongo-driver-install, your invocation would be:

scons --use-system-boost --extrapath=/usr/local --full --prefix=$HOME/mongo-driver-install install-mongoclient

You would then set your application build to use $HOME/mongo-driver-install/include and $HOME/mongo-driver-install/lib for include and library search paths as well.

Finally, please note that you can also build the driver a shared library, by passing the --sharedclient flag.

As for the crash you experienced, it is hard to debug without some additional information. If possible can you show the exact code you used to call mongo::client::initialize, and any code that ran earlier in main? Ideally, just reduce your mainline to the shortest program that demonstrates the issue and post it here.

Thanks,
Andrew

Comment by duanguoxue [ 05/Nov/13 ]

Hi,
I have clone the github master and using

"scons --use-system-boost=/usr/local/include/ mongoclient"

compiling the "libmongoclient.a" ok.

But execute my test app.
Reporting the error info:

failed to initialize the client driver: BadValue default

I and some "printf log info to mongoclient code" find in function "recursiveTopSort "

if ((*visitedNodeNames).count(currentNode.first))
return Status::OK();
if (!currentNode.second.fn)
return Status(ErrorCodes::BadValue, currentNode.first);
inProgressNodeNames->push_back(currentNode.first);

When

currentNode.first = "default"

but

currentNode.second.fn =NULL

May be I have a error using the library.

Comment by Andrew Morrow (Inactive) [ 04/Nov/13 ]

Hi guoxue.duan -

You might want to re-test with the latest code from master. We have just added new API's to explicitly manage the client driver lifecycle (see mongo/client/init.h). You can probably use these methods to successfully arrange clean driver shutdown, in particular, destroying the BackgroundJob responsible for running PeriodicTasks.

Can you please update your test to use these new APIs, re-run your checks, and post the results back?

Thanks,
Andrew

Comment by duanguoxue [ 20/Oct/13 ]

Hi, this is my test application and valgrind report. Hope can help you.

Comment by duanguoxue [ 20/Oct/13 ]

build command:

g++ -g tutorial.cpp -pthread -lmongoclient -lpthread -lboost_thread -lboost_filesystem -lboost_program_options -lboost_system -o tutorial -I /root/mongo-cxx-driver-v2.4/src/ -L /root/mongo-cxx-driver-v2.4/build/

running command:

valgrind --log-file=valgind_l_r_2.4.6_10-20.log --leak-check=full ./tutorial

"tutorial.cpp" is the modified test application.

If i modified my cxx driver with the github two pull request( https://github.com/mongodb/mongo/pull/497 ) ,I will get a clean valgind report.


And I think the "DBConnectionPool" memory leak is obvious error. "BackgroundJob" is don't free the global variable obj may have a difficult.(So MUST confirm no other influence)

Comment by duanguoxue [ 17/Oct/13 ]

Hi ,
I think the static initialization of the library also must be free,which is very important too.May be We use a library give a function to initialize the static area and release function to free static memory(I also see in libproto libgtest ,etc).

If I use "DBConnectionPool" as a local variable. I will have a continual grow memory leak.

Additional I retest the "no-show-reachable=yes" situations and I reconstruct a memory leak application.

"valgrind --leak-check=full --log-file=val2.4.6_no-show-reachable.log ./test_mg_db 128"

==3631== HEAP SUMMARY:
==3631== in use at exit: 3,320 bytes in 118 blocks
==3631== total heap usage: 929 allocs, 811 frees, 189,172 bytes allocated
==3631==
==3631== 40 bytes in 1 blocks are definitely lost in loss record 14 of 19
==3631== at 0x4A075BC: operator new(unsigned long) (vg_replace_malloc.c:298)
==3631== by 0x48AF1D: mongo::BackgroundJob::BackgroundJob(bool) (in /root/search/MTSearch/dba/test_mg_db)
==3631== by 0x447CFD: global constructors keyed to dbclient_rs.cpp (in /root/search/MTSearch/dba/test_mg_db)
==3631== by 0x4AE495: ??? (in /root/search/MTSearch/dba/test_mg_db)
==3631== by 0x4108EA: ??? (in /root/search/MTSearch/dba/test_mg_db)
==3631==
==3631== 1,600 bytes in 100 blocks are definitely lost in loss record 19 of 19
==3631== at 0x4A075BC: operator new(unsigned long) (vg_replace_malloc.c:298)
==3631== by 0x4287C8: mongo::DBConnectionPool::DBConnectionPool() (in /root/search/MTSearch/dba/test_mg_db)
==3631== by 0x411C16: main (test_mg_db.cc:51)
==3631==
==3631== LEAK SUMMARY:
==3631== definitely lost: 1,640 bytes in 101 blocks
==3631== indirectly lost: 0 bytes in 0 blocks
==3631== possibly lost: 0 bytes in 0 blocks
==3631== still reachable: 1,680 bytes in 17 blocks
==3631== suppressed: 0 bytes in 0 blocks

Comment by Andrew Morrow (Inactive) [ 01/Oct/13 ]

Hi -

Thanks for re-testing with 2.4.6.

The reports in the log are appearing because you have run valgrind with --show-reachable=yes. This is memory that was allocated, but is still referenced, therefore it has not been leaked. I believe that all of the memory listed in your report originates from the static initialization of the library. While perhaps not ideal that this memory is never reclaimed, the adverse consequences of this sort of behavior are minimal: the allocations are not repeated, therefore the memory footprint will not grow over time, which is typically the worry in a memory leak.

As to the changes in the pull request: First, you don't need to check a pointer to be non-NULL before deleting it. It is safe to call delete on a NULL pointer and it is specified to be a no-op. Second, you do not need to set the variable to NULL after deleting it, especially when operating on a member variable in a destructor, since the lifetime of the member variable terminates with the object, so the effect of the assignment to NULL is unobservable.

To demonstrate that there is indeed a memory leak, you will need to provide a program that causes the memory utilization of the process using libmongoclient to grow without bound. Please let me know if you have any further questions. Obviously, we want to ensure that using libmongoclient does not cause unbounded memory utilization in client programs.

Thanks,
Andrew

Comment by duanguoxue [ 24/Sep/13 ]

1 recompiling the cxx driver 2.4.6 and my tutorial app.
2 I have re-test the same case(valgrind --leak-check=full --show-reachable=yes --log-file=valgind_l_r_2.4.6.log ./tutorial).

More ,I find some issues,and reading the github mainline code,also have the same bugs.

Some memleak commit a pull request(https://github.com/mongodb/mongo/pull/497 ),but some I don't kown how to repair.
Example:

Ports& ports = *(new Ports());
DiagStr& _hostNameCached = *(new DiagStr);
static ErrorInfo* okInfo = new ErrorInfo(ErrorCodes::OK, "", 0);

Comment by Andrew Morrow (Inactive) [ 23/Sep/13 ]

Thank you for the report. A few comments:

  • You are using 2.4.0, which has some known issues. Can you please re-test with the most recent 2.4 release, 2.4.6, and re-post your results?
  • All but one of the items reported by valgrind are identified as 'still reachable', so these are not memory leaks.
  • All of these memory regions are owned by static initializers, so these allocations will not be repeated.

I do agree, however, that it is important for our library to be as clean as possible under valgrind so that we don't cause false positives in applications that are attempting to be valgrind clean. So I am interested in our repairing the 'definitely lost' region if this behavior is reproduced with the 2.4.6 driver.

Generated at Thu Feb 08 03:24:13 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.