13

We were hit by this bug:

http://bugs.python.org/issue1856 Daemon threads segfault during interpreter shut down.

Now I search a way to code around this bug.

At the moment the code looks like this:

while True:
    do_something()
    time.sleep(interval)

Is there a way to check if the interpreter is still usable before do_something()?

Or is it better to not do mythread.setDaemon(True) and the check if the main thread has exited?

guettli
  • 25,042
  • 81
  • 346
  • 663

2 Answers2

10

Answer to own question:

I use this pattern now: don't setDaemon(True), don't use sleep(), use parent_thread.join()

while True:
    parent_thread.join(interval)
    if not parent_thread.is_alive():
        break
    do_something()

Related: http://docs.python.org/2/library/threading.html#threading.Thread.join

guettli
  • 25,042
  • 81
  • 346
  • 663
  • I don't get it. If a child thread is not daemon, then a parent thread won't ever die (before child) and thus `is_alive` on parent will always be true. I.e. this entire check is pointless. It might work if a child thread is daemon though. – freakish Aug 07 '13 at 09:05
  • 1
    @freakish if the parent (main) thread has reached its end, is_alive() will return False, but the child thread is still alive. It works in my tests. – guettli Aug 07 '13 at 09:18
  • @guettli Hi, having similar issue here. Can you please help with explaining how you obtain `parent_thread`? – Korem Nov 04 '14 at 08:16
  • @Korem I store `parent_thread` at module level. In my case there is only one parent thread for the whole process/interpreter. – guettli Nov 04 '14 at 08:37
  • I see a similar problem, my curses screen interface is one thread, everthing else is main thread. quit is initiated by child thread ( on pressing 'q' ) - this gave me segfault on linux - going to try this solution - thanks for posting! – kollery Dec 08 '16 at 03:11
0

This is a code from threading.py module:

import sys as _sys

class Thread(_Verbose):
    def _bootstrap_inner(self):
        # some code

            # If sys.stderr is no more (most likely from interpreter
            # shutdown) use self._stderr.  Otherwise still use sys (as in
            # _sys) in case sys.stderr was redefined since the creation of
            # self.
            if _sys:
               _sys.stderr.write("Exception in thread %s:\n%s\n" % 
                   (self.name, _format_exc()))
            else:
               # some code

might be helpful. The error you see comes from else statement. So in your case:

import sys as _sys

while True:
    if not _sys:
        break/return/die/whatever
    do_something()
    time.sleep(interval)

I'm not sure if it works though (note that interpreter shutdown may happen inside do_something so you should probably wrap everything with try:except:).

Daemon threads are not necessarily bad, they can definitely speed up development process. You just have to be careful with them.

freakish
  • 54,167
  • 9
  • 132
  • 169