[zeromq-dev] Clean shutdown of malamute client zactor in python binding?
Aaron Sokoloski
asokoloski at gmail.com
Wed Feb 3 18:07:06 CET 2016
Hi folks,
I'm trying to make the python malamute binding as easy to use as possible.
I'm having trouble making sure that everything gets cleaned up correctly on
exit, though, when the client is running in a thread other than the main
thread, and the client is blocking on a call to recv (aka mlm_client_recv).
So far, I have something that works, but isn't ideal, which is to create a
"shutdown" inproc socket pair whose only purpose is to notify the recieving
end when the process gets interrupted, using a python signal handler. Then
the application code can poll both that receiving socket and the malamute
client msgpipe, and exit the receive loop when it gets a message on the
shutdown socket.
Here's the gist of that approach:
https://gist.github.com/asokoloski/02ab5affeca9be2bebdb
Although conceptually simple, this is a bit awkward, especially for
application code that may want to create multiple clients. So what I'm
trying to do is figure out a way to make everything get cleaned up
automatically. Ideally, what would happen is that the zactor thread
finishes whatever it was doing and the zactor gets destroyed, then an
exception is raised in the python thread.
Destroying the zactor from another thread is a big no-no, because zeromq
sockets are not thread safe, correct? So the thread that is doing the recv
has to wake up. We could terminate the context directly, which would make
the recv return, but that's quite abrupt, and doesn't give the zactor a
chance to shut down. We could make the recv call poll the socket
internally, periodically waking up to check if it's been interrupted, but
that seems gross, especially as it would have to poll rather quickly -- the
shutdown timeout is 200ms.
One options is to take the same approach of having a shutdown socket pair,
but try to hide it inside the python library code. Maybe the application
code just calls recv(), but inside recv() the object polls the two
sockets. But that doesn't really play nicely in the case where, say, the
application code wants to poll the malamute client and some other sockets
at the same time. It's doable, but feels complicated.
So I have lots of questions now. Is my reasoning above valid? Is this
sort of thing a problem with pure c programs as well? Does it even matter
if the zactor shuts down cleanly, aside from avoiding ugly warnings? Is
there another approach that I haven't even considered?
If there isn't a better way to do this, I can bite the bullet and make the
application code handle it, but it sure feels a bit lacking.
Thanks in advance for any help anyone can offer,
Aaron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20160203/db8a71f2/attachment.htm>
More information about the zeromq-dev
mailing list