Crash in thread on program termination

Discussion in 'Python' started by Alec Wysoker, Feb 9, 2005.

  1. Alec Wysoker

    Alec Wysoker Guest

    I have several programs that have two or more threads. The threads that are not the main thread are daemon threads, i.e. the fact that they are running should not stop the program from terminating if the main thread (the only non-daemon thread) terminates. I do not join to these threads, but just run off the end of the main module to terminate the program. I'm using Python 2.3.4. I occasionally get the following error:

    Traceback (most recent call last):
    File "C:\Python23\lib\threading.py", line 451, in __bootstrap
    self.__stop()
    File "C:\Python23\lib\threading.py", line 460, in __stop
    self.__block.notifyAll()
    File "C:\Python23\lib\threading.py", line 256, in notifyAll
    self.notify(len(self.__waiters))
    File "C:\Python23\lib\threading.py", line 238, in notify
    currentThread() # for side-effect
    TypeError: 'NoneType' object is not callable


    What seems to be happening is that at the time the thread is stopped, the threading module object is no longer in an unhealthy state. I.e. threading.currentThread is None. I hacked around this problem by substituting my own code for _Condition.notifyAll() that would not call notify() if there were no waiters to be notified. However, that merely allowed the code to get a little further, before crashing with a similar problem, i.e. threading._StringIO is None instead of being a class object.

    Traceback (most recent call last):
    File "C:\Python23\lib\threading.py", line 443, in __bootstrap
    s = _StringIO()
    TypeError: 'NoneType' object is not callable


    I turned on threading.__debug__ and threading._VERBOSE to get some debug output, and one thing that is strange is that I don't get the debugging output I expect.

    # From threading.Thread.__bootstrap():
    try:
    self.run()
    except SystemExit:
    if __debug__:
    self._note("%s.__bootstrap(): raised SystemExit", self)
    except:
    if __debug__:
    self._note("%s.__bootstrap(): unhandled exception", self)
    s = _StringIO()
    _print_exc(file=s)
    _sys.stderr.write("Exception in thread %s:\n%s\n" %
    (self.getName(), s.getvalue()))
    else:
    if __debug__:
    self._note("%s.__bootstrap(): normal return", self)
    finally:
    self.__stop() # Line 451


    I.e. I would expect to get one of the messages ('raised SystemExit', 'unhandled exception', or 'normal return') before self.__stop() is called at line 451. However, I do not see any of those messages.

    Any ideas or suggestions? I am baffled.

    Thanks,

    Alec Wysoker
    Alec Wysoker, Feb 9, 2005
    #1
    1. Advertising

  2. Alec Wysoker

    Peter Hansen Guest

    Alec Wysoker wrote:
    > I have several programs that have two or more threads. The threads
    > that are not the main thread are daemon threads, i.e. the fact
    > that they are running should not stop the program from terminating
    > if the main thread (the only non-daemon thread) terminates.
    >
    > Traceback (most recent call last):

    [...]
    > File "C:\Python23\lib\threading.py", line 238, in notify
    > currentThread() # for side-effect
    > TypeError: 'NoneType' object is not callable
    >
    > What seems to be happening is that at the time the thread is stopped, the threading
    > module object is no longer in an unhealthy state.
    > I.e. threading.currentThread is None.


    In a nutshell, the interpreter is dismantling itself while the
    daemon threads merrily continue to run -- or attempt to. During
    one of the steps in this dismantling process, the interpreter
    goes through and rebinds all the globals in all modules to the
    None object. You're seeing the effect of a daemon thread
    encountering the inevitable bad effects of this.

    For background, search the list archives and focus on messages
    written by Tim Peters. Also try Googling the web for, say,
    "python interpreter daemon thread shutdown nonetype" or
    something... there are various not entirely conclusive threads
    on the subject here and there.

    I'm not sure there is a generally acceptable solution. You'll
    notice that the ultimate response of the code in __bootstrap()
    is still to try to print to stderr... which is a harmless but
    otherwise perhaps distracting thing to do.

    In my own code where this was a bother, I have something like
    the following at the highest levels of the run() method of
    my daemon threads:

    def run(self):
    try:
    # do real stuff here
    except Exception, ex:
    if (self.isDaemon() and
    isinstance(ex, AttributeError) and
    ex[0].startswith("'NoneType'")):
    pass

    In other words, I'm attempting to catch those specific types of
    spurious error and avoid letting __bootstrap() have its say.
    At the moment, 98% of the spurious messages are gone and that's
    good enough for my purposes...

    -Peter
    Peter Hansen, Feb 9, 2005
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike Mimic

    Event after thread termination

    Mike Mimic, Jan 11, 2004, in forum: Java
    Replies:
    5
    Views:
    655
    Chris Smith
    Jan 11, 2004
  2. J. Campbell

    program termination/memory leaks

    J. Campbell, Sep 11, 2003, in forum: C++
    Replies:
    14
    Views:
    1,051
    J. Campbell
    Sep 13, 2003
  3. Eric Ries
    Replies:
    0
    Views:
    254
    Eric Ries
    Mar 29, 2005
  4. Sanjay
    Replies:
    1
    Views:
    650
    George Ter-Saakov
    Feb 21, 2007
  5. Teja

    Thread termination

    Teja, Oct 13, 2006, in forum: Python
    Replies:
    4
    Views:
    323
    Hendrik van Rooyen
    Oct 14, 2006
Loading...

Share This Page