-
Notifications
You must be signed in to change notification settings - Fork 70
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
memory leak #151
Comments
False alarm. It says possibly lost. Valgrind does not know about finalizers (and cannot reasonably be expected to). V8's garbage collector will clean it up when it sees fit to do so. |
I don't see the allocation here getting freed: https://github.com/nickdesaulniers/node-nanomsg/blob/master/src/node_nanomsg.cc#L216 (starting a new libuv poll context) why would that out-of-scope allocation be V8's responsibility? and I doubt it would be libuv's responsibility to free it |
@kkoopa I think we got a legit leak here, but yeah I see your point, not knowing about finalizers means there's a fair chance it's a false alarm.. is there a way I can trigger a GC? I want to find out what valgrind thinks right after a GC event |
Aha, I thought it was related to that patch I submitted a week ago. Nevermind then. The problem here is that To force garbage collection, run node with |
OK cool.. 🚀 i'm gonna do some digging around and report back 🔧 |
|
totally agree, but for one minor point:
it's accepting the wrapped context, see here where that gets returned, and in JS before it's later used in i think when we start doing multiplexing we oughtta check for the presence of that wrapped pointer context first, and use it first and foremost before just going and allocating a new one no matter what otherwise I think we have to clean it up and deallocate the context in |
also we're setting that buffer (context) to |
Context / socket, tomato / tomato. I must confess I did not actually read the code. I am merely speculating. The easiest way is probably to maintain an invariant on the javascript side. Set the variable to |
haha, that's awesome. Yea one of the big nanomsg benefits is that sockets are no longer contexts, (as they are in ZeroMQ), here they're just an
for now I think the simplest fix will be to follow what's being represented up in JS land, and later we might try to optimize the module by reducing the number of system calls associated w/ memory management |
ugh, easier said than done.. freeing the context seems to eliminate the mem leak, but crashes w/ inproc in a weird way.. NAN_METHOD(PollStop) {
nanomsg_socket_t *context = UnwrapPointer<nanomsg_socket_t *>(info[0]);
int r = uv_poll_stop(&context->poll_handle);
free(context);
info.GetReturnValue().Set(Nan::New<Number>(r));
} if wrapping pointer imbues v8 reference, am I trying to free v8 memory after the call to |
Yes. Just keep the code as is, apart from changing https://github.com/nickdesaulniers/node-nanomsg/blob/master/src/node_pointer.h#L22 to |
ok interesting, yea freeing that structure seems problematic especially once its typedef struct nanomsg_socket_s {
uv_poll_t poll_handle;
uv_os_sock_t sockfd;
Nan::Callback *callback;
} nanomsg_socket_t; |
Add a destructor to it. On March 3, 2016 3:01:07 AM GMT+02:00, Bent Cardan [email protected] wrote:
|
I have encountered this and tried to fix by refering to your proposed codes. NAN_METHOD(PollStop) {
nanomsg_socket_t *context = UnwrapPointer<nanomsg_socket_t *>(info[0]);
int r = uv_poll_stop(&context->poll_handle);
delete(context->callback); // <- add
info.GetReturnValue().Set(Nan::New<Number>(r));
} inline static v8::Local<v8::Value> WrapPointer(void *ptr, size_t length) {
return Nan::NewBuffer(static_cast<char *>(ptr), length).ToLocalChecked(); // <- changed
} |
@k-keisuke thanks for fixing the memory leak. I'm testing your fix today.
What does the output message from segmentation fault look like? Is there any assertion or debug message or does that seg fault go down with a silent exit? |
That ToLocalChecked is a likely culprit. On October 14, 2016 9:44:54 PM GMT+03:00, Bent Cardan [email protected] wrote:
|
Thanks.
Sorry I can't understand. |
While the stack trace mentions JSON parsing, I doubt it was the culprit. I bet things went like:
...some time later...
|
we could build this lib with |
Segmentation fault occurs in only this fix, I found. inline static v8::Local<v8::Value> WrapPointer(void *ptr, size_t length) {
return Nan::NewBuffer(static_cast<char *>(ptr), length).ToLocalChecked(); // <- changed
} I think this fix means I delegate freeing ptr to V8 garbage collector. (referenced to following link) |
I am seeing a steady growth in heap and rss memory in one of our production services that heavily uses req-rep protocol. Are there any updates on a fix for this issue? |
Does someone have a simple JS test case that repro's this? I'm happy to hook up ASAN to this to try and spot the leak. |
@nickdesaulniers Here's a simple test that send a req request every 10ms - https://github.com/redsift/node-nanomsg-leak-test . You can take heap snapshots by sending a 'kill -USR2 '. Inspecting the heap in Chrome dev tools shows no leaks in js code but the 'System Objects' size increases steadily. Thanks for looking into this. |
what i'm seeing after running @deepakprabhakara's test case: -------- <LEAK> -------
{"growth":20719656,"reason":"heap growth over 5 consecutive GCs (9m 50s) - 120.57 mb/hr"}
-------- </LEAK> -------
-------- <LEAK> -------
{"growth":22130304,"reason":"heap growth over 5 consecutive GCs (10m 22s) - 122.15 mb/hr"}
-------- </LEAK> -------
-------- <LEAK> -------
{"growth":28205736,"reason":"heap growth over 5 consecutive GCs (13m 17s) - 121.5 mb/hr"}
-------- </LEAK> ------- |
build with `npm i --asan=true`. This will use a build that links in asan at runtime. The odd split in .gyp files exists because we want to compile nanomsg with asan instrumentation, but when we link our node_namomsg.node shared object we want to remind gyp to link asan's runtime library. This can likely also be done for Linux, but I haven't tested. Also, we segfault off the bat with this. I don't have time to look into it, but at least it builds correctly.
build with `npm i --asan=true`. This will use a build that links in asan at runtime. The odd split in .gyp files exists because we want to compile nanomsg with asan instrumentation, but when we link our node_namomsg.node shared object we want to remind gyp to link asan's runtime library. This can likely also be done for Linux, but I haven't tested. Also, we segfault off the bat with this. I don't have time to look into it, but at least it builds correctly.
Hi @nickdesaulniers, just wondering if you had any success spotting the leak using ASAN. |
I tried running it with asan=true but end up with this on Mac Sierra:- ==8057==ERROR: Interceptors are not working. This may be because AddressSanitizer is loaded too late (e.g. via dlopen). Please launch the executable with: Any idea how I can fix this? |
@deepakprabhakara sorry, see my commit message for the asan patch (latest). You don't run with any env vars set. You build the library with a gyp arg, then everything should just work. Problem is we get a segfault off the bat. I don't have time to track down what that is. |
I sent pull request to fix this memory leak as above. Please check the detail. Thanks. |
thanks @m-ohuchi i'm looking at it |
Thanks @m-ohuchi, nice work! |
@deepakprabhakara, @reqshark how long do you have to run the test case to repro? I can run the test against master with no leaks. I did change the require to |
memwatch-next doesn't even compile for node v7.2.1. What version of node was used to repro this? marcominetti/node-memwatch#24 |
ah got it, you have to run it for a very long time. We should find out a way to speed that up and add it to our test suite. |
I really really don't want to have to maintain code with synchronization. The double call of At the risk of having to maintain that, I've authored #169 which takes the same approach of using It's a smaller change and removes more code. I think it will be more maintainable. I would like to add some kind of memory leak test to our test suite. And I do very much appreciate @m-ohuchi taking a crack at fixing this. |
Thanks @nickdesaulniers to accept my code. I'm glad I could contribute this project.
I think so, too. I don't mind your changes to my code, I know synchronization often cause a problem and also free operation is weird. I think my code should be improved to much more safer way. |
Thanks for your code pointing to where the leaks were occurring. Thanks all, it's good to get long standing issues resolved. |
Thanks everyone, excellent work closing the leak! |
PollSendSocket leaks. At least valgrind thinks so.
cc: @nickdesaulniers, @kkoopa, @tcr
The text was updated successfully, but these errors were encountered: