python - How to explain the reentrant RuntimeError caused by printing in signal handlers? -
code:
# callee.py import signal import sys import time def int_handler(*args): in range(10): print('interrupt', args) sys.exit() if __name__ == '__main__': signal.signal(signal.sigint, int_handler) signal.signal(signal.sigterm, int_handler) while 1: time.sleep(1)
# caller.py import subprocess import sys def wait_and_communicate(p): out, err = p.communicate(timeout=1) print('========out==========') print(out.decode() if out else '') print('========err==========') print(err.decode() if err else '') print('=====================') if __name__ == '__main__': p = subprocess.popen( ['/usr/local/bin/python3', 'callee.py'], stdout=sys.stdout, stderr=subprocess.pipe, ) while 1: try: wait_and_communicate(p) except keyboardinterrupt: p.terminate() wait_and_communicate(p) break except subprocess.timeoutexpired: continue
simply execute caller.py
, press ctrl+c
, program raise runtimeerror: reentrant call inside <_io.bufferedwriter name='<stdout>'>
randomly. documentation learn signal handlers called asynchronously, , in case 2 signals sigint(ctrl+c
action) , sigterm(p.terminate()
) sent @ same time, causing race condition.
however, post learn signal
module doesn't execute signal handler inside low-level (c) handler. instead, it sets flag, , interpreter checks flag between bytecode instructions , invokes python signal handler. in other words, while signal handlers may mess control flow in main thread, bytecode instruction atomic.
this seems contradict result of example program. far concerned, print
, implicit _io.bufferedwriter
both implemented in pure c, , calling print
function should consume 1 bytecode instruction (call_function
). confused: within 1 uninterrupted instruction on 1 thread, how can function reentrant?
i'm using python 3.6.2.
Comments
Post a Comment