<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">I've got an application which makes fairly heavy use of daemon threads to perform 'background' processing and various other long-running tasks that are likely to block.<div><br></div><div>My original understanding of threading.Thread's daemon threads was that I could safely fire them off and essentially forget about managing them from the main thread's perspective as long as they don't do anything that's not thread safe -- eg I can fire them off, let them do their background twiddling and safely let the threading machinery manage their lifespan assuming that</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>1. the 'background twiddling' is threadsafe and</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>2. the thread can safely 'die' at any point without requiring a shutdown procedure</div><div><br></div><div>Some coding later and I learn this isn't exactly the case, as there as in an additional requirement on the use of daemon threads -- they can't reference anything in the global namespace else they may raise exceptions at interpreter shutdown. This is because as part of the shutdown procedure, the interpreter sets all global variables to None. A daemon thread may run while this is occuring/after it occured but before the process exits, attempt to access a global variable and then throw an exception. The exception may get printed if the interpreter catches/prints it before the process exits.</div><div><br></div><div>I garnered this understanding from this problem description -- (although all mistakes in description are my own)</div><div><br></div><div><div><a href="http://bugs.python.org/issue1722344">http://bugs.python.org/issue1722344</a></div><div><br></div></div><div>In this bug report they are discussing an interpreter problem which affects non-daemon threads -- I'm not attempting to claim that I'm being affected by an interpreter bug, I reference this link only because it contains good descriptions of the interpreter shutdown process as well as the additional requirements the interpreter places on 'daemon' threads (beyond just being 'thread-safe'):</div><div><blockquote type="cite"><span class="Apple-style-span" style="font-family: monospace, Verdana, Geneva, 'Bitstream Vera Sans', Helvetica, sans-serif; font-size: 12px; line-height: 17px; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">When Python begins to shutdown it takes
each module and sets each variable in the global namespace to None. If a
thread has not terminated before the interpreter terminates then the
thread tries to use a global variable which has been set to None.
This is not about to change since this occurs because of coding
"errors". You must make sure that either your thread is as safe as a
__del__ method (which means no global namespace access) or you can't let
the app exit until you are positive all of your threads have terminated,
not just asked them to shutdown since this is all asynchronous.</pre></span></blockquote></div><blockquote type="cite"><span class="Apple-style-span" style="font-family: monospace, Verdana, Geneva, 'Bitstream Vera Sans', Helvetica, sans-serif; font-size: 12px; line-height: 17px; "><pre style="white-space: pre-wrap; word-wrap: break-word; ">> > which means no global namespace access
> Does that mean that you cannot use len and range in a Thread?
No, it means you have to be careful if you do. Shutting down properly
will take care of things. Otherwise you need to save a reference
locally (either on an object or as a local variable) and use that
reference instead of relying on the one defined in the global
namespace.</pre></span></blockquote><div>Here's an example of one such traceback from one of my application runs:</div><div><br></div><div><div><blockquote type="cite">Exception in thread Thread-11 (most likely raised during interpreter shutdown):</blockquote><blockquote type="cite">(pydev-2.6) ncohen$ </blockquote><div><br></div><div><div>In this run, the process exited before even one traceback finished printing but this will be timing dependent, -- sometimes I'll see tracebacks from many backgrounds threads and sometimes just snippets like this. They will typically be AttributeError's or TypeError's resulting from failed attempts to access variables from the global namespace. Here's a longer example from another run:</div></div></div><div><br></div><div><div></div><blockquote type="cite"><div>Traceback (most recent call last):</div><div> File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 525, in __bootstrap_inner</div><div> File "/Users/ncohen/software/viis/viis/apps/permassh.py", line 184, in run</div><div> File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/SocketServer.py", line 224, in serve_forever</div><div><type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'select'</div><div><br></div><div>Traceback (most recent call last):</div><div> File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 525, in __bootstrap_inner</div><div> File "/Users/ncohen/software/viis/viis/apps/permassh.py", line 184, in run</div><div> File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/SocketServer.py", line 224, in serve_forever</div><div><type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'select'</div><div>Exception in thread Thread-7 (most likely raised during interpreter shutdown):</div><div>Traceback (most recent call last):</div><div> File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/threading.py", line 525, in __bootstrap_inner</div><div> File "/Users/ncohen/pydev-2.6/lib/python2.6/site-packages/paramiko/transport.py", line 1571, in run</div><div> File "/Users/ncohen/pydev-2.6/lib/python2.6/site-packages/paramiko/transport.py", line 1386, in _log</div><div> File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/logging/__init__.py", line 1105, in log</div><div><type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'IntType'</div><div>(pydev-2.6)breathe-wifi:viis.webapp ncohen$ </div></blockquote></div><div><div><blockquote type="cite">(pydev-2.6) ncohen$ </blockquote><div><br></div></div></div><div>My question concerns whether or not daemon threads have the inconvenient 'no references to globals()' requirement imposed only by the interpreter shutdown process or if there are other additional reasons for the requirement.</div><div><br></div><div>0. is it possible for me to consider it 'safe' to have code which can trigger the above exceptions during interpreter shutdown?</div><div>1. if it is possible, and it turns out I'm certain what I'm doing is safe, is there a good way to squelch those error reports?</div><div></div><blockquote type="cite"><div></div></blockquote><div><br></div><div>Is there perhaps some way to customize the value that all the globals get set to during interpreter shutdown? -- i think it would work for me to replace the None to which all globals are set with an object which</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>1. returns None as usual if accessed from a non-daemon thread</div><div><span class="Apple-tab-span" style="white-space:pre"> </span>2. blocks forever if accessed from a daemon thread, or maybe calls an 'emergency exit' function, (but I don't think the emergency exit function would get any guarantees that it would complete running before the process exited) ...</div><div><br></div><div>In my case I don't always have control over the daemon threads creation or lifespan -- in this particular app, I'm using the paramiko library which uses daemon thread(s) 'behind the scenes' to simplify its networking code ...</div><div><br></div><div>Looking forward to any comments/advice or name calling.</div><div><br></div><div>Thanks,</div><div>Ben</div></div><br><div>
<span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><div><span class="Apple-style-span" style="font-size: 12px; "><div>Ben Cohen</div><div>Programmer/Analyst (STS)</div><div>Scripps Institution of Oceanography</div><div><a href="mailto:ncohen@ucsd.edu">ncohen@ucsd.edu</a></div></span></div></span>
</div>
<br></body></html>