Skip to content

Instantly share code, notes, and snippets.

@yinyin
Created September 16, 2019 17:19
Show Gist options
  • Save yinyin/8d1cd7c98596e86c5718e8a313c7474e to your computer and use it in GitHub Desktop.
Save yinyin/8d1cd7c98596e86c5718e8a313c7474e to your computer and use it in GitHub Desktop.
An experiment of signal reentrance in Python
#!/usr/bin/env python
"""
The result of signal handler reentrance in Python 2.7 and 3.7 might different:
# For Python 2.7
The signal handler will run in order.
```
$ python2 signal_handler_reentrance.py
20190917011037:INFO:__main__:PID = 4219 (ref-command: kill -USR1 4219; sleep 2; kill -USR1 4219)
20190917011037:DEBUG:__main__:in loop 1
20190917011047:DEBUG:__main__:in loop 2
20190917011048:INFO:__main__:in signal handler: t=1568653848, attempt=0
20190917011049:INFO:__main__:in signal handler: t=1568653848, attempt=1
20190917011049:INFO:__main__:in signal handler: t=1568653848, attempt=2
...
20190917011054:INFO:__main__:in signal handler: t=1568653848, attempt=12
20190917011054:INFO:__main__:in signal handler: t=1568653848, attempt=13
20190917011055:INFO:__main__:in signal handler: t=1568653848, attempt=14
20190917011055:INFO:__main__:leaving signal handler: t=1568653848
20190917011055:INFO:__main__:in signal handler: t=1568653855, attempt=0
20190917011056:INFO:__main__:in signal handler: t=1568653855, attempt=1
20190917011056:INFO:__main__:in signal handler: t=1568653855, attempt=2
...
20190917011101:INFO:__main__:in signal handler: t=1568653855, attempt=12
20190917011102:INFO:__main__:in signal handler: t=1568653855, attempt=13
20190917011102:INFO:__main__:in signal handler: t=1568653855, attempt=14
20190917011103:INFO:__main__:leaving signal handler: t=1568653855
20190917011103:DEBUG:__main__:in loop 3
```
# For Python 3.7
The 1st signal hander will suspend on the arrival of 2nd signal.
```
$ /opt/python-3.7/bin/python3 signal_handler_reentrance.py
20190917011309:INFO:__main__:PID = 4350 (ref-command: kill -USR1 4350; sleep 2; kill -USR1 4350)
20190917011309:DEBUG:__main__:in loop 1
20190917011318:INFO:__main__:in signal handler: t=1568653998, attempt=0
20190917011318:INFO:__main__:in signal handler: t=1568653998, attempt=1
20190917011319:INFO:__main__:in signal handler: t=1568653998, attempt=2
20190917011319:INFO:__main__:in signal handler: t=1568653998, attempt=3
20190917011320:INFO:__main__:in signal handler: t=1568653998, attempt=4
20190917011320:INFO:__main__:in signal handler: t=1568654000, attempt=0
20190917011320:INFO:__main__:in signal handler: t=1568654000, attempt=1
20190917011321:INFO:__main__:in signal handler: t=1568654000, attempt=2
...
20190917011326:INFO:__main__:in signal handler: t=1568654000, attempt=12
20190917011326:INFO:__main__:in signal handler: t=1568654000, attempt=13
20190917011327:INFO:__main__:in signal handler: t=1568654000, attempt=14
20190917011327:INFO:__main__:leaving signal handler: t=1568654000
20190917011327:INFO:__main__:in signal handler: t=1568653998, attempt=5
20190917011328:INFO:__main__:in signal handler: t=1568653998, attempt=6
20190917011328:INFO:__main__:in signal handler: t=1568653998, attempt=7
...
20190917011331:INFO:__main__:in signal handler: t=1568653998, attempt=12
20190917011331:INFO:__main__:in signal handler: t=1568653998, attempt=13
20190917011332:INFO:__main__:in signal handler: t=1568653998, attempt=14
20190917011332:INFO:__main__:leaving signal handler: t=1568653998
20190917011332:DEBUG:__main__:in loop 2
```
"""
import logging
import time
import signal
import os
_log = logging.getLogger(__name__)
class SignalHandlerReEntranceExp01:
def handler(self, *args, **kwds): # pylint: disable=unused-argument
t = int(time.time())
for attempt in range(15):
_log.info("in signal handler: t=%d, attempt=%d", t, attempt)
time.sleep(0.5)
_log.info("leaving signal handler: t=%d", t)
def loop(self):
loop_count = 0
while True:
loop_count = loop_count + 1
try:
_log.debug("in loop %d", loop_count)
time.sleep(10)
except Exception:
_log.exception("caught exception in loop %d", loop_count)
def main():
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(name)s:%(message)s", datefmt="%Y%m%d%H%M%S")
exp_obj = SignalHandlerReEntranceExp01()
signal.signal(signal.SIGUSR1, exp_obj.handler)
pid_value = os.getpid()
_log.info("PID = %d (ref-command: kill -USR1 %d; sleep 2; kill -USR1 %d)", pid_value, pid_value, pid_value)
exp_obj.loop()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment