PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mais qui donc set ce signal handler ? 6

jeudi 25 février 2016 à 08:59

Le module signal permet de réagir aux signaux envoyés par l’OS, par exemple celui qui vous annonce qu’il va vous défoncer la gueule (SIGTERM) ou que vous votre mémoire n’est plus ce qu’elle était (SIGSEGV).

Mais le problème, c’est que rien n’annonce qu’un signal est attrapé. Pire, quand on enregistre un handler pour un signal, ça écrase le précédent. Yep, c’est très con.

ç’aurait été plus malin d’avoir un truc comme propose le DOM, genre addEventListener, qui accumule les handlers pour un event donné, mais non, on override.

Donc parfois, une lib tierce partie se permet un petit handling de signal sur le pouce, comme ça, sans demander la permission, provoquant chaos et moult jurons. Car des signaux, y en a pas mal:

>>> import signal
>>> [s for s in dir(signal) if s.isupper()]
['ITIMER_PROF', 'ITIMER_REAL', 'ITIMER_VIRTUAL', 'NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 'SIGCLD', 'SIGCONT', 'SIGFPE', 'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL', 'SIGPIPE', 'SIGPOLL', 'SIGPROF', 'SIGPWR', 'SIGQUIT', 'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP', 'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGUSR1', 'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ', 'SIG_BLOCK', 'SIG_DFL', 'SIG_IGN', 'SIG_SETMASK', 'SIG_UNBLOCK']

En plus, certains sont Windows only, d’autres Unix only…

Et pour faciliter les choses, les handlers peuvent être des entiers (bon, des enums dont __eq__ accepte les entiers…):

>>> type(signal.getsignal(signal.SIGKILL))
<enum 'Handlers'>
 
>>> type(signal.getsignal(signal.SIGINT) )
<class 'builtin_function_or_method'>

Voici un petit snippet pour checker si un sacripant n’est pas en train de vous brouter le signal:

>>> import signal
>>> handlers = {}
>>> for s in dir(signal):
...     if s.isupper(): # on chope uniquement les constantes
...         try:
...             handler = getattr(signal, s) # quel handler pour ce signal ?
...             if callable(handler): # on ignore SIG_DFL, SIG_IGN, etc.
...                 handlers[s] = handler # ok, on a un truc gégé !
...         except ValueError:
...            pass
>>> print(handlers[s])

On s’en sert pas souvent, mais je me suis dit que je ferai passer le mot.