<div>Re: not exiting without killing:</div>I just needed to add thread.setDaemon(True), so the device threads do exit properly now. <div><br></div><div>committed/pushed to git.<br><br></div><div>-MinRK</div><div><br><div class="gmail_quote">

On Mon, Jul 12, 2010 at 22:10, MinRK <span dir="ltr">&lt;<a href="mailto:benjaminrk@gmail.com">benjaminrk@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<br><br><div class="gmail_quote"><div><div></div><div class="h5">On Mon, Jul 12, 2010 at 22:04, Brian Granger <span dir="ltr">&lt;<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>On Mon, Jul 12, 2010 at 9:49 PM, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt;<br>
&gt; On Mon, Jul 12, 2010 at 20:43, Brian Granger &lt;<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Min,<br>
&gt;&gt;<br>
&gt;&gt; On Mon, Jul 12, 2010 at 4:10 PM, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt; I&#39;ve been thinking about this, and it seems like we can&#39;t have a<br>
&gt;&gt; &gt; responsive<br>
&gt;&gt; &gt; rich control connection unless it is in another process, like the old<br>
&gt;&gt; &gt; IPython daemon.<br>
&gt;&gt;<br>
&gt;&gt; I am not quite sure I follow what you mean by this.  Can you elaborate?<br>
&gt;<br>
&gt; The main advantage that we were to gain from the out-of-process ipdaemon was<br>
&gt; the ability to abort/kill (signal) blocking jobs. With 0MQ threads, the only<br>
&gt; logic we can have in a control/heartbeat thread must be implemented in<br>
&gt; GIL-free C/C++. That limits what we can do in terms of interacting with the<br>
&gt; main work thread, as I understand it.<br>
<br>
</div>Yes, but I think it might be possible to spawn an external process to<br>
send a signal back to the process.  But I am not sure about this.<br>
<div><br>
&gt;&gt;<br>
&gt;&gt; &gt; Pure heartbeat is easy with a C device, and we may not even<br>
&gt;&gt; &gt; need a new one. For instance, I added support for the builtin devices of<br>
&gt;&gt; &gt; zeromq to pyzmq with a few lines, and you can have simple is_alive style<br>
&gt;&gt; &gt; heartbeat with a FORWARDER device.<br>
&gt;&gt;<br>
&gt;&gt; I looked at this and it looks very nice.  I think for basic is_alive<br>
&gt;&gt; type heartbeats this will work fine.  The only thing to be careful of<br>
&gt;&gt; is that 0MQ sockets are not thread safe.  Thus, it would be best to<br>
&gt;&gt; actually create the socket in the thread as well.  But we do want the<br>
&gt;&gt; flexibility to be able to pass in sockets to the device.  We will have<br>
&gt;&gt; to think about that issue.<br>
&gt;<br>
&gt;<br>
&gt; I wrote/pushed a basic ThreadsafeDevice, which creates/binds/connects inside<br>
&gt; the thread&#39;s run method.<br>
&gt; It adds bind_in/out, connect_in/out, and setsockopt_in/out methods which<br>
&gt; just queue up arguments to be called at the head of the run method. I added<br>
&gt; a tspong.py in the heartbeat example using it.<br>
<br>
</div>Cool, I will review this and merge it into master.<br>
<br></blockquote><div> </div></div></div><div>I&#39;d say it&#39;s not ready for master in one particular respect: The Device thread doesn&#39;t respond to signals, so I have to kill it to stop it. I haven&#39;t yet figured out why this is happening; it might be quite simple.</div>


<div><br></div><div>I&#39;ll push up some unit tests tomorrow</div><div><div></div><div class="h5"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


Cheers,<br>
<font color="#888888"><br>
Brian<br>
</font><div><div></div><div><br>
&gt;&gt;<br>
&gt;&gt; &gt; I pushed a basic example of this (examples/heartbeat) to my pyzmq fork.<br>
&gt;&gt; &gt; Running a ~3 second numpy.dot action, the heartbeat pings remain<br>
&gt;&gt; &gt; responsive<br>
&gt;&gt; &gt; at &lt;1ms.<br>
&gt;&gt;<br>
&gt;&gt; This is great!<br>
&gt;&gt;<br>
&gt;&gt; Cheers,<br>
&gt;&gt;<br>
&gt;&gt; Brian<br>
&gt;&gt; &gt; -MinRK<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; On Mon, Jul 12, 2010 at 12:51, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; On Mon, Jul 12, 2010 at 09:15, Brian Granger &lt;<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a>&gt;<br>
&gt;&gt; &gt;&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; On Fri, Jul 9, 2010 at 3:35 PM, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt;&gt; &gt;&gt;&gt; &gt; Brian,<br>
&gt;&gt; &gt;&gt;&gt; &gt; Have you worked on the Heartbeat Device? Does that need to go in 0MQ<br>
&gt;&gt; &gt;&gt;&gt; &gt; itself,<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; I have not.  Ideally it could go into 0MQ itself.  But, in principle,<br>
&gt;&gt; &gt;&gt;&gt; we could do it in pyzmq.  We just have to write a nogil pure C<br>
&gt;&gt; &gt;&gt;&gt; function that uses the low-level C API to do the heartbeat.  Then we<br>
&gt;&gt; &gt;&gt;&gt; can just run that function in a thread with a &quot;with nogil&quot; block.<br>
&gt;&gt; &gt;&gt;&gt; Shouldn&#39;t be too bad, given how simple the heartbeat logic is.  The<br>
&gt;&gt; &gt;&gt;&gt; main thing we will have to think about is how to start/stop the<br>
&gt;&gt; &gt;&gt;&gt; heartbeat in a clean way.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; &gt; or can it be part of pyzmq?<br>
&gt;&gt; &gt;&gt;&gt; &gt; I&#39;m trying to work out how to really tell that an engine is down.<br>
&gt;&gt; &gt;&gt;&gt; &gt; Is the heartbeat to be in a separate process?<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; No, just a separate C/C++ thread that doesn&#39;t hold the GIL.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; &gt; Are we guaranteed that a zmq thread is responsive no matter what an<br>
&gt;&gt; &gt;&gt;&gt; &gt; engine<br>
&gt;&gt; &gt;&gt;&gt; &gt; process is doing? If that&#39;s the case, is a moderate timeout on recv<br>
&gt;&gt; &gt;&gt;&gt; &gt; adequate<br>
&gt;&gt; &gt;&gt;&gt; &gt; to determine engine failure?<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; Yes, I think we can assume this.  The only thing that would take the<br>
&gt;&gt; &gt;&gt;&gt; 0mq thread down is something semi-fatal like a signal that doesn&#39;t get<br>
&gt;&gt; &gt;&gt;&gt; handled.  But as long as the 0MQ thread doesn&#39;t have any bugs, it<br>
&gt;&gt; &gt;&gt;&gt; should simply keep running no matter what the other thread does (OK,<br>
&gt;&gt; &gt;&gt;&gt; other than segfaulting)<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; &gt; If zmq threads are guaranteed to be responsive, it seems like a<br>
&gt;&gt; &gt;&gt;&gt; &gt; simple<br>
&gt;&gt; &gt;&gt;&gt; &gt; pair<br>
&gt;&gt; &gt;&gt;&gt; &gt; socket might be good enough, rather than needing a new device. Or<br>
&gt;&gt; &gt;&gt;&gt; &gt; even<br>
&gt;&gt; &gt;&gt;&gt; &gt; through the registration XREP socket.<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; That (registration XREP socket) won&#39;t work unless we want to write all<br>
&gt;&gt; &gt;&gt;&gt; that logic in C.<br>
&gt;&gt; &gt;&gt;&gt; I don&#39;t know about a PAIR socket because of the need for multiple<br>
&gt;&gt; &gt;&gt;&gt; clients?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; I wasn&#39;t thinking of a single PAIR socket, but rather a pair for each<br>
&gt;&gt; &gt;&gt; engine. We already have a pair for each engine for the queue, but I am<br>
&gt;&gt; &gt;&gt; not<br>
&gt;&gt; &gt;&gt; quite seeing the need for a special device beyond a PAIR socket in the<br>
&gt;&gt; &gt;&gt; heartbeat.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; &gt; Can we formalize exactly what the heartbeat needs to be?<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; OK, let&#39;s think.  The engine needs to connect, the controller bind.<br>
&gt;&gt; &gt;&gt;&gt; It would be nice if the controller didn&#39;t need a separate heartbeat<br>
&gt;&gt; &gt;&gt;&gt; socket for each engine, but I guess we need the ability to track which<br>
&gt;&gt; &gt;&gt;&gt; specific engine is heartbeating.   Also, there is the question of to<br>
&gt;&gt; &gt;&gt;&gt; do want to do a reqest/reply or pub/sub style heartbeat.  What do you<br>
&gt;&gt; &gt;&gt;&gt; think?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; The way we talked about it, the heartbeat needs to issue commands both<br>
&gt;&gt; &gt;&gt; ways. While it is used for checking whether an engine remains alive, it<br>
&gt;&gt; &gt;&gt; is<br>
&gt;&gt; &gt;&gt; also the avenue for aborting jobs.  If we do have a strict heartbeat,<br>
&gt;&gt; &gt;&gt; then I<br>
&gt;&gt; &gt;&gt; think PUB/SUB is a good choice.<br>
&gt;&gt; &gt;&gt; However, if heartbeat is all it does, then we need a _third_ connection<br>
&gt;&gt; &gt;&gt; to<br>
&gt;&gt; &gt;&gt; each engine for control commands. Since messages cannot jump the queue,<br>
&gt;&gt; &gt;&gt; the<br>
&gt;&gt; &gt;&gt; engine queue PAIR socket cannot be used for commands, and a PUB/SUB<br>
&gt;&gt; &gt;&gt; model<br>
&gt;&gt; &gt;&gt; for heartbeat can _either_ receive commands _or_ have results.<br>
&gt;&gt; &gt;&gt; control commands:<br>
&gt;&gt; &gt;&gt; beat (check alive)<br>
&gt;&gt; &gt;&gt; abort (remove a task from the queue)<br>
&gt;&gt; &gt;&gt; signal (SIGINT, etc.)<br>
&gt;&gt; &gt;&gt; exit (engine.kill)<br>
&gt;&gt; &gt;&gt; reset (clear queue, namespace)<br>
&gt;&gt; &gt;&gt; more?<br>
&gt;&gt; &gt;&gt; It&#39;s possible that we could implement these with a PUB on the<br>
&gt;&gt; &gt;&gt; controller<br>
&gt;&gt; &gt;&gt; and a SUB on each engine, only interpreting results received via the<br>
&gt;&gt; &gt;&gt; queue&#39;s<br>
&gt;&gt; &gt;&gt; PAIR socket. But then every command would be sent to every engine, even<br>
&gt;&gt; &gt;&gt; though many would only be meant for one (too inefficient/costly?). It<br>
&gt;&gt; &gt;&gt; would<br>
&gt;&gt; &gt;&gt; however make the actual heartbeat command very simple as a single send.<br>
&gt;&gt; &gt;&gt; It does not allow for the engine to initiate queries of the controller,<br>
&gt;&gt; &gt;&gt; for instance a work stealing implementation. Again, it is possible that<br>
&gt;&gt; &gt;&gt; this<br>
&gt;&gt; &gt;&gt; could be implemented via the job queue PAIR socket, but that would only<br>
&gt;&gt; &gt;&gt; allow for stealing when completely starved for work, since the job<br>
&gt;&gt; &gt;&gt; queue and<br>
&gt;&gt; &gt;&gt; communication queue would be the same.<br>
&gt;&gt; &gt;&gt; There&#39;s also the issue of task dependency.<br>
&gt;&gt; &gt;&gt; If we are to implement dependency checking as we discussed (depend on<br>
&gt;&gt; &gt;&gt; taskIDs, and only execute once the task has been completed), the engine<br>
&gt;&gt; &gt;&gt; needs to be able to query the controller about the tasks depended upon.<br>
&gt;&gt; &gt;&gt; This<br>
&gt;&gt; &gt;&gt; makes the controller being the PUB side unworkable.<br>
&gt;&gt; &gt;&gt; This says to me that we need two-way connections between the engines<br>
&gt;&gt; &gt;&gt; and<br>
&gt;&gt; &gt;&gt; the controller. That can either be implemented as multiple connections<br>
&gt;&gt; &gt;&gt; (PUB/SUB + PAIR or REQ/REP), or simply a PAIR socket for each engine<br>
&gt;&gt; &gt;&gt; could<br>
&gt;&gt; &gt;&gt; provide the whole heartbeat/command channel.<br>
&gt;&gt; &gt;&gt; -MinRK<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; Brian<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; &gt; -MinRK<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt;<br>
&gt;&gt; &gt;&gt;&gt; --<br>
&gt;&gt; &gt;&gt;&gt; Brian E. Granger, Ph.D.<br>
&gt;&gt; &gt;&gt;&gt; Assistant Professor of Physics<br>
&gt;&gt; &gt;&gt;&gt; Cal Poly State University, San Luis Obispo<br>
&gt;&gt; &gt;&gt;&gt; <a href="mailto:bgranger@calpoly.edu" target="_blank">bgranger@calpoly.edu</a><br>
&gt;&gt; &gt;&gt;&gt; <a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a><br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; --<br>
&gt;&gt; Brian E. Granger, Ph.D.<br>
&gt;&gt; Assistant Professor of Physics<br>
&gt;&gt; Cal Poly State University, San Luis Obispo<br>
&gt;&gt; <a href="mailto:bgranger@calpoly.edu" target="_blank">bgranger@calpoly.edu</a><br>
&gt;&gt; <a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a><br>
&gt;<br>
&gt;<br>
<br>
<br>
<br>
</div></div>--<br>
<div><div></div><div>Brian E. Granger, Ph.D.<br>
Assistant Professor of Physics<br>
Cal Poly State University, San Luis Obispo<br>
<a href="mailto:bgranger@calpoly.edu" target="_blank">bgranger@calpoly.edu</a><br>
<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a><br>
</div></div></blockquote></div></div></div><br>
</blockquote></div><br></div>