
On 27 October 2004 15:08, Glynn Clements wrote:
Simon Marlow wrote:
So basically you're saying that if runProcess is to be used in a system()-like way, that is the parent is going to wait synchronously for the child, then the parent should be ignoring SIGQUIT/SIGINT. On the other hand, if runProcess is going to be used in a popen()-like way, then the parent should not be ignoring SIGQUIT/SIGINT.
Exactly.
The current interface doesn't allow for controlling the behaviour in this way.
Yep.
So the current signal handling in runProcess is wrong, and should probably be removed. What should we have instead? We could implement the system()-like signal handling for System.Cmd.system only, perhaps.
Well, probably for system and rawSystem.
I've now fixed system and rawSystem to do something more appropriate on POSIX systems: they now disable SIGINT and SIGQUIT in the parent, and reset these signals to SIG_DFL in the child. This isn't completely correct, but it's better than before. runProcess and friends don't do any signal handling. I think this covers most of the useful situations. If you want to do the same thing in both parent and child, or handle in the parent and SIG_DFL in the child: use runProcess. If you want to ignore in the parent and SIG_DFL in the child: use System.Cmd.{system,rawSystem}. To handle in the parent and ignore in the child: unfortunately not directly supported. I realise this doesn't address the library design issues you raised, but as you pointed out there doesn't seem to be a good platform-independent solution here. Cheers, Simon

Simon Marlow wrote:
I've now fixed system and rawSystem to do something more appropriate on POSIX systems: they now disable SIGINT and SIGQUIT in the parent, and reset these signals to SIG_DFL in the child. This isn't completely correct, but it's better than before.
Just a reminder, as the original discussion was back in October: The POSIX system() behaviour is to ignore the signals in the parent (before the fork()) and "un-ignore" them in the child, i.e. restore whichever handlers where in effect upon entry to system(), before the parent ignored them. E.g.: sighandler_t old_quit = signal(SIGQUIT, SIG_IGN); sighandler_t old_intr = signal(SIGINT , SIG_IGN); pid_t pid = fork(); if (pid == 0) { /* child */ signal(SIGQUIT, old_quit); signal(SIGINT , old_intr); execve(...); } else if (pid > 0) { /* parent */ waitpid(...); } signal(SIGQUIT, old_quit); signal(SIGINT , old_intr); The effect is almost the same as ignoring them in the parent *after* the fork(), but that has a potential race condition, i.e. if the signal arrived after the fork() but before the parent ignored it. Ignoring before the fork() and restoring in the child eliminates that possibility. Any actual signal handlers (i.e. pointers to actual functions rather than SIG_IGN or SIG_DFL) will be reset to SIG_DFL by execve(), as the handler functions won't exist in the new program. But if the signal was already being ignored on entry to system(), it will continue to be ignored in the child (this is the key difference). Also, the POSIX system() function blocks SIGCHLD in the parent, but I don't know whether that's appropriate in GHC. The reason is to prevent interactions between existing SIGCHLD handlers and the child process which system() creates (e.g. an existing SIGCHLD handler might call wait() and accidentally reap system()'s child).
I think this covers most of the useful situations. If you want to do the same thing in both parent and child, or handle in the parent and SIG_DFL in the child: use runProcess. If you want to ignore in the parent and SIG_DFL in the child: use System.Cmd.{system,rawSystem}. To handle in the parent and ignore in the child: unfortunately not directly supported.
As it stands, you can have whatever behaviour you want in the parent: set the desired handling before calling system/rawSystem/runProcess then set it back afterwards. However, this will cease to be true for system/rawSystem if you change them so that the child restores the handlers to their state upon entry.
I realise this doesn't address the library design issues you raised, but as you pointed out there doesn't seem to be a good platform-independent solution here.
Yes; any programs which perform non-trivial process management will
have to use platform-specific functionality.
--
Glynn Clements
participants (2)
-
Glynn Clements
-
Simon Marlow