GHC handling of signals

Consider the following program: import System.IO import System.IO.Error import System.Posix.Signals main = do installHandler sigPIPE Default Nothing c <- readFile "/usr/share/dict/words" putStrLn c `catchIOError` \e -> hPutStrLn stderr (show e) hPutStrLn stderr "I survived" Compile with ghc and run as ./test | true As expected, you see nothing further displayed, since according to `man 7 signal` the default for SIGPIPE is to terminate the program, which happens before the exception handler has a chance to run. Without the line where the signal handler gets installed the behavior is different: You'll see: <stdout>: commitBuffer: resource vanished (Broken pipe) I survived Apparently the GHC runtime does something like installHandler sigPIPE Ignore Nothing This is not a complaint, I find the behavior quite reasonable and much more predictable than the default (why should I not be able to catch EPIPE and continue?). The question is whether it is documented how the GHC runtime treats signals and if yes where? Cheers Ben -- I would rather have questions that cannot be answered, than answers that cannot be questioned. -- Richard Feynman

quoth Ben Franksen
Consider the following program:
import System.IO import System.IO.Error import System.Posix.Signals
main = do installHandler sigPIPE Default Nothing c <- readFile "/usr/share/dict/words" putStrLn c `catchIOError` \e -> hPutStrLn stderr (show e) hPutStrLn stderr "I survived"
Compile with ghc and run as
./test | true
As expected, you see nothing further displayed, since according to `man 7 signal` the default for SIGPIPE is to terminate the program, which happens before the exception handler has a chance to run.
Without the line where the signal handler gets installed the behavior is different: You'll see:
<stdout>: commitBuffer: resource vanished (Broken pipe) I survived
Apparently the GHC runtime does something like
installHandler sigPIPE Ignore Nothing
This is not a complaint, I find the behavior quite reasonable and much more predictable than the default (why should I not be able to catch EPIPE and continue?).
The question is whether it is documented how the GHC runtime treats signals and if yes where?
For more on this, see https://mail.haskell.org/pipermail/glasgow-haskell-users/2010-August/019082.... That thread doesn't really go into why GHC interferes with SIGPIPE. I personally would lean towards letting the operating system defaults prevail, but whatever, I don't do Haskell anyway. The discussion there is more about why Ignore, rather than SIG_IGN. Donn

On Sat, May 27, 2023 at 03:53:55PM +0200, Ben Franksen wrote:
Apparently the GHC runtime does something like
installHandler sigPIPE Ignore Nothing
This is not a complaint, I find the behavior quite reasonable and much more predictable than the default (why should I not be able to catch EPIPE and continue?).
The question is whether it is documented how the GHC runtime treats signals and if yes where?
In the case of SIGPIPE, the relevant documentation can be found in: https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/ffi.html?high... -- Viktor.

Am 27.05.23 um 16:46 schrieb Donn Cave:
For more on this, see https://mail.haskell.org/pipermail/glasgow-haskell-users/2010-August/019082....
Am 27.05.23 um 16:52 schrieb Viktor Dukhovni:
On Sat, May 27, 2023 at 03:53:55PM +0200, Ben Franksen wrote:
Apparently the GHC runtime does something like
installHandler sigPIPE Ignore Nothing
This is not a complaint, I find the behavior quite reasonable and much more predictable than the default (why should I not be able to catch EPIPE and continue?).
The question is whether it is documented how the GHC runtime treats signals and if yes where?
In the case of SIGPIPE, the relevant documentation can be found in:
https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/ffi.html?high...
Thanks for both of your answers. The location in the docs is a bit obscure, I wouldn't look for it there, but at least it is documented. For posterity, what GHC runtime does is to install a do-nothing handler, rather than set it to SIG_IGN. This is so that this setting won't be inherited by child processes (as it would be with SIG_IGN). Cheers Ben -- I would rather have questions that cannot be answered, than answers that cannot be questioned. -- Richard Feynman
participants (3)
-
Ben Franksen
-
Donn Cave
-
Viktor Dukhovni