-
Notifications
You must be signed in to change notification settings - Fork 666
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
Interrupting library calls #77
Comments
Generally you could use the posix signal alarm for that. But since you mention sockets, it is safer to actually not abort the syscall, but use setsockopt with option SO_RCVTIMEO to set an input timeout on the listening socket instead. |
Your analysis is correct. Currently the library doesn't directly support interrupting calls into the library. That said the library does support extracting the socket fd from the connection object. So it is possible with a bit if work to use the select system call with a timeout parameter of your choosing to make the library behave in a non blocking manner. The SimpleAmqpClient library which wraps rabbitmq-c does this as an example when consuming messages. |
I'm using the library on Windows (with Visual Studio 2010) to build a service (that runs in a background) that waits for messages from other application through RabbitMQ and then executes some other actions. Since I wanted to make the service well I should implement options to pause and to stop the service. Both of which (certainly the second one) requires me to interrupt any call, especially the blocking ones. So are the posix features available to me? How? And making calls with timeout is not a reasonable option here. Making short timeout would make the code do much more than needed while making a long timeout puts me in a risk of service manager deciding that the service is no longer responsive and stable. Is running the whole thing on a different thread and then killing it brutally, possibly closing the socket from the main thread first (or later) an option? Would starting a new thread and reinitializing the library (creating connection, exchange, ...) work? (A solution that just now came to my mind.) |
Also another possibility: is alanxz/libamqp-cpp capable of such interrupting? Is it mature and stable enough for use in production code? |
Win32/WinSock2 does support the [select()](http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85\).aspx) system call. Given your use case I would look into using the SimpleAmqpClient library wrapper. It doesn't allow a true interrupt (e.g., using a SIG_ALARM or whatever), but given a short timeout (1-5 seconds) you could get something that is pretty close. This library has already been developed so you're that much farther ahead :) A good thing to think about: how frequently are you going to be pausing/stopping the service, and how fast does it need to be at pausing? alanxz/libamqp-cpp is far from complete (I believe the state I left it in is that it can successfully connect to the broker and maybe do some RPC-style AMQP method calls (e.g., queue.declare). It was an experiment I started and never got around to finishing. |
Actually in this specific case I don't expect any pause. Stopping the service would be done (I guess) with every turning off the computer. And then the time limits are rather strong (but 1-5 seconds should be enough) since it could be for example turning off due to low battery... Somehow I don't like the timeout solution since this is actually semi-active waiting while it should be passive. But looks like this is the only way to go. Thanks for assistance and please consider this feature. To me it seems important (and rather natural expectation to be able to interrupt a long blocking call in network environment). |
Why can't you have multiple threads in the service: one is your event loop that alternates between checking for a message from the broker, and checking for a shutdown notification of some kind from another thread. That's how I've seen a lot of these kinds of services work at least on windows. I'm unlikely to add an interruptable interface based on signals. Their implementation across platforms is very inconsistent and you quickly run into problems of "what happens when more than one library wants to handle a signal?" That said an asynchronous interface is something I hope to add in the future, which I think will solve a lot of use cases, such as yours. |
Maybe may approach is wrong but I’m used to idea that if a thread has nothing to do it should do nothing and not repeatedly check if there is anything to do. Since such checking is a needless work ideologically not far from active waiting. In fact it is active waiting with improvements. Not to mention that you end up with a difficult dilemma: how often should you check (alternate)? If you do it often to seem responsive your waiting is more active. If you do it rarely you seem unresponsive. Why put yourself into such dilemma if you might skip that issue? As to how to implement interrupting I’m of little use here. I’m not used to POSIX which the library seems to be using. I don’t know much about signals and if they are as bad as you describe then surly they are not a solution: just a change into different problem. As to “interrupting” itself maybe you understood me to strictly. As a library user I don’t care how it is implemented under the hood. I just want to be able to make a call like In native Windows API a call to |
The other thing I failed to mention above is that makes a cancellation interface a non-starter is currently rabbitmq-c is not thread-safe: meaning instances of I do realize that ideally you want your app to be NOTHING while waiting for I/O. Having a polling loops sucks down unnecessary CPU cycles, and if you're running on something with limited power you're potentially waking up a processor core when maybe you don't have to. Unfortunately, even if I did manage to resolve the concurrency issues above, cancelling network I/O is a minefield as you go across different platforms, as there are different levels of support for this. |
Maybe another approach: is it possible to not use library-provided socket handling and do I/O on your own? That way I could implement interrupting I/O the way I like and just feed raw data to the library functions to parse it in "AMQP way". I'm not sure how difficult would it be even if the library would (reasonably) allow that. The idea just came to my mind. |
I have not tried this yet, but I think you could get it done with the The unwritten (as of yet) documentation on this function: int amqp_handle_input(amqp_connection_state_t state,
amqp_byte_t received_data,
amqp_frame_t *decoded_frame) Takes a chunk of WARNING: this modifies the internal state of the Inputs: Returns: Errors
|
Is the still the current situation? Attempting to terminate a client, where the polling thread is in |
I'm not sure this is a good place to ask (most likely not). But I don't know any better place (a feature I miss in github) and quick browsing through the code makes me think this might not be possible at all and thus would be an "issue" in fact.
So is there a way to interrupt library calls?
For library user it would be useful to be able to interrupt any calls that could take long (in particular those which block execution until some input on a socket). And keep consistency and stability of the data/library so any actions could be (as much as possible) taken again without complete reload.
The text was updated successfully, but these errors were encountered: