Is het veilig om print aan te roepen in een Python signal handler?

We hebben ook geleerd dat Python signal handlers onverwacht re-entrant zijn: als er een signaal binnenkomt terwijl een Python signal handler wordt uitgevoerd, kan de signal handler opnieuw worden aangeroepen midden in de eerste aanroep.

Wat gebeurt er als een signal handler re-entrant wordt aangeroepen midden in een aanroep naar print? Laten we dit stress-testen door onszelf een snelle barrage aan signalen te sturen:

import os, signal, subprocess

def sighandler(_signo, _frame):
    print("signal received")

signal.signal(signal.SIGUSR1, sighandler)
subprocess.run("for x in {1..50}; do kill -USR1 %s; done" % os.getpid(), shell=True)

Het uitvoeren van dit programma op mijn machine produceerde het volgende:

File "multiple_signals.py", line 6, in sighandler
    print("signal received")
File "multiple_signals.py", line 6, in sighandler
    print("signal received")
File "multiple_signals.py", line 6, in sighandler
    print("signal received")
[Previous line repeated 2 more times]
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>

Het testprogramma laat zien dat onder extreme omstandigheden het aanroepen van print in een signal handler ertoe kan leiden dat je programma crasht. Ik wil benadrukken dat dit extreme omstandigheden vereist: het is onwaarschijnlijk dat een echt programma met deze condities te maken krijgt. Zelfs dan is falen met een exception acceptabeler dan de mogelijke gevolgen van onveilige signal handlers in C, waaronder deadlock, corrupte datastructuren en stille fouten.

Ik beschouw dit dan ook als een stukje "signals trivia" en niet als een praktische overweging voor het schrijven van signal handlers – hoewel ik nog steeds afraad om niet-triviaal werk in een signal handler uit te voeren.