-
Notifications
You must be signed in to change notification settings - Fork 108
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
azmq hangs on outstanding async_receive calls #99
Comments
@ahundt I've tried to understand a code and I'm a bit confused. What is the purpose of having three threads (main, |
I could probably just call Looking at it again, I think an earlier version also didn't necessarily quit after n iterations. Instead the Also, the reason I created some |
Also, this test tries to do something very simple:
The reason receive could be called more times than send is because the sender could die unexpectedly if they are two separate machines! Even if that is the case, the program should exit properly when the time comes to do so, such as if I had set a timer that decided no more sends would occur. |
@ahundt regarding signal handling, to handle it properly you need to register your signal handler. Note that in this signal handler you should do nothing except setting an atomic variable. |
@ahundt regarding scenarioI have more questions:
|
I expect the io_service to be destroyed successfully and the application to quit even if there are outstanding async_receive calls. Essentially, you should be able to stop the application at any time should a user request it modulo some short delay if necessary. |
I believe standard asio exhibits this behavior. If I do something like the following pseudocode:
The program should exit successfully. I think something similar to the above, though it might need some changes to make it correct, would not exit with azmq because the io_service destruction would fail due to the outstanding async_receive call. |
@ahundt signals handling it's not as simple as you think, especially in multi-thread process. Please read the links that I posted above. |
I'm confused, how do signals relate to this issue? The problem is that azmq hangs when there are outstanding async_receive calls. I have no problems with signal handlers. Sorry for the stray comments where I mention signal handlers. Those should have been removed, and I have taken them out now. |
Could you try running the code I posted originally for the "minimal example"? It will never exit due to a bug in azmq. It will hang at the |
I've updated the original description with details about the expected behavior and the actual behavior of the code. Please let me know if the issue is still unclear. I'm sorry that I made it so confusing before. |
Thank you. I like that it's clear now that it's not related to signals at all :) |
The reason the code hangs is not because of AZMQ bug but because |
Issue #100 created. Using of |
ah yes, good point w.r.t. weak pointers! thanks! I also like how you described issue #100 that sounds like a very appropriate feature to have. |
You may want some version of my code here, perhaps simplified, to serve as a unit test for an example when socket::close() is implemented. |
Also, could it be sensible for there to be a way to read with a timeout. It seems this has come up in the past. https://stackoverflow.com/questions/10858719/cancel-async-read-due-to-timeout |
You should understand that reading with timeout is the same for azmq socket as for standard asio socket. There are several ways to implement this and the solution highly depends on a way you do networking in your application. Usually you need a timer (like Sorry, I don't have time to check links. |
Can I close this issue out then? I will implement close() in next week or so. |
sure, I haven't tested code with weak_ptr yet, but if I come across an issue I'll just make note here when the time comes. Thanks for the help! |
In general, with Asio under C++11 I tend to use the idiom of capturing by We can re-open if necessary, and I am hopeful that i will have a patch On Sun, Aug 16, 2015 at 9:54 AM, Andrew Hundt notifications@github.com
|
great! is there an example of your typical usage style, perhaps in the tests? I'd love to use it as a reference |
I might even be able to fix up my code at the top and make it into an example you could include for new users. |
Unfortunately all code I have with examples like this is the IP of my On Sun, Aug 16, 2015 at 12:41 PM, Andrew Hundt notifications@github.com
|
@rodgert bump I'm still dealing with this issue and would love if I could get a quick example! |
Is a timer necessary in order to read with a timeout? Should |
@zmb3 this will work only for a synchronous receive. For an asynchronous one a separate mechanism like asio timer is required. |
Thanks @oliora - I eventually came to the same conclusion. |
@oliora yeah an example with weak_ptr would be perfect. For the async receive presumably a timer would keep getting extended on each successful receive and then if it does fire call |
@ahundt the on-timer action is application specific. Simple apps would like to just call |
Sorry, been off the air for a while. Where does this stand? Is there an issue here? @ahundt The documentation on std::shared_ptr std::weak_ptr at http://en.cppreference.com/w/cpp/memory seem fairly self evident how they work and don't really have anything to do with AZMQ per-se. My point originally was that if you held a socket via std::shared_ptr (or perhaps some accompanying state type, e.g. a "server"), instead of capturing that shared_ptr in a lambda passed to a handler (thus bumping the reference and keeping the instance alive inadvertently), you capture it as a std::weak_ptr. The lambda capture will at that point no longer prevent the socket from being destroyed, and when the lambda is invoked, it would usually have an error_code indicating that the handler had been terminated, and even if for some reason it didn't indicate an error, a call to std::weak_ptr::lock() to get the instance you wanted to have available in the handler, would indicate that the socket had been destroyed, so the handler should just gracefully exit. |
yes, I think I understand this now. I have more time at the moment so over the next week I plan to try modifying my test to pass a weak_ptr to lambda capture, then when the lambda is called and only if it is valid convert it to a shared_ptr again. This should allow things to exit. I'll test this out in a small test function. I don't remember my original expectations, but I guess perhaps my original expectation may have been that all the handlers would be called with an error code if things were trying to go down. |
Termination is hard :) Ideally all handlers should get called with an error code, but only if the On Wednesday, May 18, 2016, Andrew Hundt notifications@github.com wrote:
|
The following minimal example generates a few extra receive calls. The expected behavior is that the sockets and io_service should be possible to shut down and destroy while an async_receive call is outstanding. However, the actual behavior of the code below is that the application hangs and cannot exit due to what I believe is an azmq bug:
I'm running d1f609d on OS X with zmq zeromq: stable 4.1.2 (bottled), HEAD from homebrew.
The text was updated successfully, but these errors were encountered: