Mais qui donc set ce signal handler ?


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.

6 thoughts on “Mais qui donc set ce signal handler ?

  • Kje

    Si ça arrive souvent il serait peut être plus simple de faire un monkey-patch de signal pour accumuler les handlers plutôt que de les écraser. Ainsi la lib externe ne risquerai pas de les écraser.

  • Sam Post author

    Oui mais si la lib fait un gethandler derrière, qu’est-ce que tu lui renvoies qui garantie que son code ne casse pas ? C’est tout le problème du monkeypatch.

  • Atrament

    Encore un truc que je reviendrai chercher dans quelques mois, et qui m’économisera une paire d’heures à me gratter la tête.

    Presque pas de typos, j’en trouve qu’une. “S’aurait été” > “Ç’aurait été”

  • rm_ass

    Pour vos test ‘SIGUSR1’ et ‘SIGUSR2’ sont dispo pour faire joujou !

  • paulez

    Ça me parait logique que la librairie signal n’autorise qu’un handler par signal, étant donné que c’est comme ça que l’OS fonctionne. Le comportement est cohérent avec le système je trouve ça mieux. De plus ça peut être un peu foireux de les accumuler, par exemple si on autorise deux handlers pour SIGINT (interrupt from keyboard), et que le premier termine le programme, l’autre ne sera pas exécuté, et si on change l’ordre d’exécution ça ne fera pas la même chose. Donc c’est le bordel d’accumuler les signal handlers !

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.