Skip to content

Odd issues related to Spawn.__del__ #76

@luckyh

Description

@luckyh

For years I had seen a few odd issues, for instances:

08:29:49 DEBUG| [stderr] Exception 
08:29:49 DEBUG| [stderr] RuntimeError
08:29:49 DEBUG| [stderr] : 
08:29:49 DEBUG| [stderr] RuntimeError('cannot join current thread',)
08:29:49 DEBUG| [stderr]  in 
08:29:49 INFO | Running 'true'
08:29:49 DEBUG| [stderr] <module 'threading' from '/usr/lib64/python2.7/threading.pyc'>
08:29:49 DEBUG| [stderr]  ignored
22:17:31 DEBUG| [stderr] Exception ignored in: 
22:17:31 DEBUG| [stderr] <function Spawn.__del__ at 0x7f8be362eee0>
22:17:31 DEBUG| [stderr] 

22:17:31 DEBUG| [stderr] Traceback (most recent call last):

22:17:31 DEBUG| [stderr]   File "/usr/local/lib/python3.9/site-packages/aexpect-1.6.0-py3.9.egg/aexpect/client.py", line 229, in __del__

22:17:31 DEBUG| [stderr]     
22:17:31 DEBUG| [stderr] self.close()
22:17:31 DEBUG| [stderr] 

22:17:31 DEBUG| [stderr]   File "/usr/local/lib/python3.9/site-packages/aexpect-1.6.0-py3.9.egg/aexpect/client.py", line 365, in close

22:17:31 DEBUG| [stderr]     
22:17:31 DEBUG| [stderr] hook(self)
22:17:31 DEBUG| [stderr] 

22:17:31 DEBUG| [stderr]   File "/usr/local/lib/python3.9/site-packages/aexpect-1.6.0-py3.9.egg/aexpect/client.py", line 673, in _join_thread

22:17:31 DEBUG| [stderr]     
22:17:31 DEBUG| [stderr] thread = self.tail_thread
22:17:31 DEBUG| [stderr] 

22:17:31 DEBUG| [stderr] AttributeError
22:17:31 DEBUG| [stderr] : 
22:17:31 DEBUG| [stderr] 'RemoteSession' object has no attribute 'tail_thread'
22:17:31 DEBUG| [stderr] 

Recently I just took a look on that, and it turns out that the issues are related to Spawn.__del__ dealing with some conditions (e.g. sys.exit, handling signals ...). So here comes a question: can we provide a method to explicitly perform Spawn.__del__ instead, or is it possible to make __del__ bug free in our case?

Here is a simple reproducer to trigger the issues easier.
(Note: the worst case here is the program would be stuck at SystemExit: 0, but fortunately so far this rarely happens during test executions.)

import signal
import sys
import threading
import time

def bar():
    open(__file__, 'r').close()

def handler(n, s):
    sys.exit(0)

class Foo(object):

    def __init__(self):
        self.thread = threading.Thread(target=bar)

    def run(self):
        self.thread.start()

    def __del__(self):
        self.close()

    def close(self):
        self.thread.join()


if __name__ == '__main__':
    signal.signal(signal.SIGALRM, handler)
    signal.alarm(1)
    while True:
        f = Foo()
        f.run()
$ for i in {1..10}; do python2.7 r.py; done
Exception RuntimeError: RuntimeError('cannot join thread before it is started',) in <bound method Foo.__del__ of <__main__.Foo object at 0x7f782105bf10>> ignored
Exception AttributeError: "'Foo' object has no attribute 'thread'" in <bound method Foo.__del__ of <__main__.Foo object at 0x7fa57c99f250>> ignored
Exception AttributeError: "'Foo' object has no attribute 'thread'" in <bound method Foo.__del__ of <__main__.Foo object at 0x7f238a745f10>> ignored
Exception SystemExit: 0 in <bound method Foo.__del__ of <__main__.Foo object at 0x7f2a6aca3090>> ignored
...
$ for i in {1..10}; do python3.9 r.py; done
Exception ignored in: <function Foo.__del__ at 0x7efff607c280>
Traceback (most recent call last):
  File "/tmp/r.py", line 21, in __del__
    self.close()
  File "/tmp/r.py", line 24, in close
    self.thread.join()
AttributeError: 'Foo' object has no attribute 'thread'
Exception ignored in: <function Foo.__del__ at 0x7fed8e99a280>
Traceback (most recent call last):
  File "/tmp/r.py", line 21, in __del__
  File "/tmp/r.py", line 24, in close
  File "/usr/lib64/python3.9/threading.py", line 1028, in join
RuntimeError: cannot join thread before it is started
Exception ignored in: <function Foo.__del__ at 0x7f1895342280>
Traceback (most recent call last):
  File "/tmp/r.py", line 21, in __del__
    self.close()
  File "/tmp/r.py", line 24, in close
    self.thread.join()
  File "/usr/lib64/python3.9/threading.py", line 1033, in join
    self._wait_for_tstate_lock()
  File "/usr/lib64/python3.9/threading.py", line 1051, in _wait_for_tstate_lock
    self._stop()
  File "/usr/lib64/python3.9/threading.py", line 989, in _stop
    with _shutdown_locks_lock:
  File "/tmp/r.py", line 10, in exit
    sys.exit(0)
SystemExit: 0
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions