New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Most basic example is full of memory leaks #193
Comments
Most of these appear to be leaks inside dependencies upon dlopen() of them. I am not very concerned about a one-time leak at time of init that will be cleaned up by the kernel at process exit. If you are, please try to investigate it as I am not. I am more concerned with continual leaks during usage that can be addressed in MLT's code. Some modules can have complex dependency graphs such as gtk2, qt, jackrack, and frei0r. I advise you to move all installed modules out of the way and test with one module at-a-time or with libmltcore.so plus whatever else.
mlt_factory_init() registers mlt_factory_close() with atexit(), and mlt_factory_close() calls mlt_repository_close(). So, yeah, don't delete that pointer. |
I modified the test code a bit:
Valgrind seems to have problem when using dlopen, so I switched to clang's AddressSanitizer. With no plugin available, only the Repository pointer leaks:
I then tested the plugins one at a time:
So I think we see here some leaks that happen in the modules themselves, but I suspect that some of the leaks are mlt's fault. Specifically those that happen in mlt_property_set_string for example. Other question, how can we prevent the Repository pointer from leaking? |
We can remove the call to mlt_repository_close() inside the destructor since that is done in Mlt::Factory::close(). It is done there because mlt_factory_init() creates the repository such that mlt_factory_close() should delete it. Some apps have no need for Mlt::Repository and need only call Mlt::Factory::init() and Mlt::Factory::close(). |
The change to Repository was made in commit a3188e3. |
This commit solves the problem when there is no plugin. |
For frei0r, one source of the leaks are the line looking registering the metadata
(factory.c:461, 470 and 479)
What am I missing? |
See commit a134539. mlt_repository_register_metadata() used to take a mlt_properties that it would take ownership. That no longer happens directly but instead when mlt_repository_metadata() invokes the callback and handles the return pointer. As a result, the important note is confusing and needs to be relocated to the doxygen comment for mlt_metadata_callback. As for frei0r, fill_param_info() frees the callback data ( |
The investigation goes on! This works as expected, the call to the mlt_register function seems to work exactly the same way (I see all the effects registered). But this time the LeakDetector doesn't catch anything... |
I'm having the same issue with the most basic example as well, but I'm using a C# / SWIG wrapper. Below is the code I'm using which very closely replicates the core of @alcinos example with some extra to track memory and iterate over the video generation.
The following is a screenshot of the memory usage at the baseline (blue box prior to running any MLT-related code) and after iterations 1 - 6. The following is a suspect stack trace acquired from a full memory dump. After each iteration of my test there is a new thread with this same stack trace. Any idea why this may be happening? We cannot realistically take our application into production until we can get the memory under control. Thank you. |
I should note that my above example does not leak memory when the consumer is "xml". |
@ryno1234 You might be observing some side effects of memory pooling in mlt_pool. Not saying that is the only culprit, but it is going to affect tests like yours. You can compile MLT with |
@ddennedy, you mentioned that I will be compiling MLT with Thank you for your quick response by the way. This is my primary focus at the moment and your input is really appreciated. UPDATE
Any other suggestions on either detecting the leak and / or approaching the task of multiple generation executions back to back? I would think this would be something that would affect pretty much any user. |
Looks like we may be leaking threads. In the screenshot below ( Shouldn't this thread be freed once done with its work? I haven't deciphered the code entirely here, but I do see that near the bottom of |
You are not calling I should mention that if you test using the null consumer set property terminate_on_pause=1 to have proper end-of-stream handling; otherwise, it spins forever on the last frame. Regarding back-to-back execution architecture, many applications serialize to XML and then process that with melt in a child process to provide process isolation and to facilitate troubleshooting by having a job XML on record. |
@ddennedy, your comment is solid-gold sir. This helps immensely. Calling Do you want me to open up a new issue to track regarding the is_stopped/stop functionality or do you intend to leave it as is? For now, I will explicitly call stop. |
Yes please file that separate issue about stop. |
Compiling and running this simplified version of src/examples/play.cpp (basically the same without a consumer):
That code triggers a lot of leaks detected by valgrind:
Since a decent amount of them come from the factory construction, I tried to get the pointer to the Mlt::Repository that is returned by Factory::init(), and delete it before the end, but that triggers a Segfault instead. Am I missing something?
The text was updated successfully, but these errors were encountered: