<div dir="ltr">Ah, the threading situation seems to be more diresome than I thought.  I believe the following code is unsafe to run.  <div><br></div><div>=== Problem code ===</div><div><br></div><div><div>import IPython.display</div><div>from IPython.html import widgets</div><div>import threading</div><div>from numpy.random import randint</div><div><br></div><div>isw1=widgets.IntSlider()</div><div>IPython.display.display(isw1)</div><div><br></div><div>isw2=widgets.IntSlider()</div><div>IPython.display.display(isw2)</div><div><br></div><div>def randoset(wid,N):</div><div>    for i in range(N):</div><div>        wid.value=randint(0,50)</div><div><br></div><div>t1=threading.Thread(target=randoset,args=[isw1,100])</div><div>t2=threading.Thread(target=randoset,args=[isw2,100])</div><div>t1.start()</div><div>t2.start()</div></div><div><br class="">This code produces malformed message errors for me in the jupyterhub terminal output.<br></div><div><br></div><div>I believe this is because all widgets seem to share the same iopub_socket and write to it whenever the user changes a traitlet.  And of course zmq sockets aren't threadsafe.</div><div><br></div><div>=== A few potential solutions === </div><div class="gmail_extra"><br></div><div class="gmail_extra">1) "Quick" -- Wrap iopub_socket in a threadsafe wrapper.  Surround every important function call in a mutex.</div><div class="gmail_extra">2) "Hintjens-approved" -- Give every single widget its own inproc PUB socket.  We'd have to spin up an extra thread (or a greenlet in some pre-extant thread?  I don't really understand what the different IPython threads do...but I could find out...) with a SUB socket to collect them all together and forward them all out on iopub_socket.</div><div class="gmail_extra">3) "Dirty" -- Wrap IPython.kernel.zmq.session.Session.send inside a mutex.  Are there use-cases where anybody besides Session actually does anything with iopub_socket?</div><div class="gmail_extra"><br></div><div class="gmail_extra">=== Motivation ===</div><div class="gmail_extra"><br></div><div class="gmail_extra">I think there could be valid use-cases for widgets which display results from polling external resources, e.g. widgets which keep track of EC2 instances, widgets which monitor IPython.parallel workerbees, etc.</div><div class="gmail_extra"><br></div><div class="gmail_extra">=== Conclusion ===</div><div class="gmail_extra"><br></div><div class="gmail_extra">I'd be happy to attack this problem, if you guys think it would be useful.  If so, let me know what would be a good general direction, and I'll put together a pull request.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Keep warm!</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div style="font-size:12.7272720336914px">Jackson Loper</div><div style="font-size:12.7272720336914px">Pattern Theory Group</div><div style="font-size:12.7272720336914px">Division of Applied Math</div><div style="font-size:12.7272720336914px">Brown University</div><div style="font-size:12.7272720336914px"><br></div><div style="font-size:12.7272720336914px">PS. I love the new text editor feature in the ipython master branch!  My days of vim-over-ssh aren't over yet (NERDTree and push-notification of filechange detection are still too useful to me when logging on from multiple machines) but I can see the end in sight!</div></div>







</div>