4 ms·
Is it safe to call print in a Python signal handler?
- IgorPartola 1mo agoWhat’s really fun is mixing signal handling and threads, especially on Linux. There is a simple way to do it and about a thousand ways that include at least one gotcha.
- zbentley 1mo agoWhat’s the simple way? Self-pipe?
- tyffanypastecf 1mo agoSelf-pipe, yeah, except in Python you don't have to build it. signal.set_wakeup_fd() is exactly that: hand it an fd (or a socket on Windows) and the interpreter writes the signal number to it. Then you select/poll that fd in your normal loop and do the actual work outside the handler. asyncio uses it under the hood for add_signal_handler. The other one that plays nicely with threads is blocking the signals everywhere with pthread_sigmask and parking one dedicated thread in sigwait(). Both are in the stdlib on Unix. signalfd is nicer than either but it's Linux only, which is why set_wakeup_fd usually wins if you care about portability.
- megagpt3 1mo agoHe considers it safe if it's unlikely to crash? That's also true in C. Calling printf in a C signal handler is likely to work. So why does he consider it important in C but "not a practical consideration" in Python? It's more likely to crash in Python than in C because the signal handler takes longer to execute.
- lmz 1mo agoThe article mentions that the Python handler is run outside of the C handler context and so is not subject to the C safety restrictions. It will not crash since the interpreter only calls the Python handler when it is safe. It will however not protect against reentrancy issues in the Python handler. The C printf function is not async signal safe and is one of the examples in the manual: https://man7.org/linux/man-pages/man7/signal-safety.7.html https://man7.org/linux/man-pages/man7/signal-safety.7.html
- megagpt3 1mo agoBut it did crash. Did we read the same article? He shows the output it prints when it crashes.
- Uptrenda 1mo agoAnd when you combine it with event loops and multiple OSes + python versions it gets even more difficult. Don't get me wrong: I love python, but shut down / cleanup is kind of a pain in the ass. If someone built a (good) lib for this it would probably be quite popular.
- nine_k 1mo agoPOSIX signals are broken by design, alas: https://lwn.net/Articles/414618/ https://lwn.net/Articles/414618/ Python or not, almost nothing is safe inside a signal handler.
- knome 1mo agothe first line of the article points out that python isn't run in the POSIX C handler. that just sets a flag for the interpreter to act on. the python issue is an unsafe re-entrant handling strategy in the interpreter.
- masklinn 1mo agoAnd this is explained in more details in the first article of the series.
- zaphirplane 1mo agoToo funny
- inigyou 1mo agoCertain signals are true user-mode interrupts, like SIGTERM and some of the ones glibc uses to implement pthreads. The ones related to application logic must only be handled with signalfd if you want any semblance of reliability.
- pjmlp 1mo agoExactly, the only safe thing to do in a signal is set a variable for other code to react on, also they completely mess up in multi-threaded code.
- germandiago 1mo agoThat is exactly what I do: set an stomic variable and do yhings outside of the handler.
- masklinn 1mo ago
- deleted 1mo ago[deleted]
- charcircuit 1mo agoI don't understand how this is still a problem in 2026. Signals should just come in via a new thread and it would solve all the complexity around them. Everyone has known the current way it works is extremely limited in what you can safely do. This whole pause the execution of what's currently running and then run some extra code somewhere else turned out to not be a good idea.
- inigyou 1mo agoThey should come in via signalfd unless they're the moral equivalent of a non-maskable interrupt.
- charcircuit 1mo agoThat is also good, but requires apps be rewritten to read from signalfd. With the separate thread approach you can get away without having to rewrite programs.
- inigyou 1mo agoIncorrect. With the separate thread approach you added a lot of new race conditions.
- charcircuit 1mo agoIn practice I don't think there would be that many. You could even pause execution of the thread that would have gotten the signal to make it even safer.
- shawn_w 1mo agoAnd for people who want to use something other than Linux?
- lmz 1mo agoBSD kqueue, Solaris ports.
- jrumbut 1mo agoI think the author undersells the significance of this. I could easily picture someone writing code that boils down to the example, all it requires is a flood of signals and a print statement. If your program generates signals, it could generate a flood unintentionally. If you put a print statement in the handler, you can get this result. It's not terribly surprising, but good to know.
- fenestella 1mo ago[flagged]
- time4tea 1mo agoBetteridge
- andrewstuart 1mo ago[flagged]