Skip to content

The cherrypy.engine can't handle DummyThreads on Python 3.4 #1342

@ghost

Description

Originally reported by: Joel Rivera (Bitbucket: cyraxjoe, GitHub: cyraxjoe)


I'm making a plugin to integrate Winpdb to CherryPy and I was having an issue with threads half-stopped on the block method of the cherrypy.engine (wspb) and it turns out that the problem is with a fix on cpython which set the _stop method body as pass and therefore never executing the expected method of the threading.Thread.

In particular this method sets the property: _is_stopped to True and because of that, the method threading.Thread.isAlive is unusable on the _DummyThread instances on Python 3.4. The problem was introduced after fixing the Issue 18808 of cpython the added a call to a new method _wait_for_tstate_loc that makes an assertion to the _is_stopped property and therefore ending with an AssertionError when the cherrypy.engine.block method reach the isAlive call.

After the isAlive call on the block method there is a comment which states:

 Note that any dummy (external) threads are always daemonic.

And indeed is true, but the AssertionErrorgets raised before reaching that line on Python 3.4.

This is an example of the resulting traceback:

#!python
[03/Oct/2014:20:22:47] ENGINE Waiting for child threads to terminate...
Traceback (most recent call last):
  File "/usr/lib64/python3.4/runpy.py", line 170, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib64/python3.4/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/home/joe/repos/arrive/arrive/devserv/__main__.py", line 102, in <module>
  File "/home/joe/repos/arrive/arrive/devserv/__main__.py", line 98, in main

  File "/home/joe/repos/arrive/arrive/devserv/__main__.py", line 82, in run_with_debugger
    cherrypy.engine.block()
  File "/home/joe/env/arrive/lib/python3.4/site-packages/cherrypy/process/wspbus.py", line 335, in block
    t.isAlive() and
  File "/usr/lib64/python3.4/threading.py", line 1119, in is_alive
    self._wait_for_tstate_lock(False)
  File "/usr/lib64/python3.4/threading.py", line 1075, in _wait_for_tstate_lock
    assert self._is_stopped
AssertionError

I suggest that we can change the isinstance validation of the _MainThread to:

  isinstance(t, (threading._MainThread, threading._DummyThread))

And set it before the isAlive call on the if conditional expression:

#!python
if (
      t != threading.currentThread() and
      not isinstance(t, (threading._MainThread, threading._DummyThread)) and
      t.isAlive()
   ):

This is valid from python 2.4 up to 3.4.

I can make this change, but I'm looking on a second opinion on this issue.


Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions