
My apologies if I misinterpreted your comments. There appear to be some use cases and conventions here that I'm not altogether familiar with. 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. The current interface doesn't allow for controlling the behaviour in this way. 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. Cheers, Simon On 26 October 2004 23:38, Glynn Clements wrote:
Having looked at the latest version of the Process library, it appears that my earlier comments about signal handling may have been misinterpreted.
First, my comments regarding the handling of SIGINT/SIGQUIT were specific to system(). The C system() function ignores these signals in the parent while the child is executing. However, this doesn't necessarily apply to other functions; e.g. popen() doesn't ignore these signals, and runProcess probably shouldn't either.
With system(), the parent blocks until the child is finished, so if the user presses Ctrl-C to kill the "currently executing" process, they probably want to kill the child. If the parent wants to die on Ctrl-C, it can use WIFSIGNALED/WTERMSIG to determine that the child was killed and terminate itself.
OTOH, with popen(), the parent continues to run alongside the child, with the child behaving as a "slave", so the parent will normally want to control the signal handling.
Ideally, system() equivalents (e.g. system, rawSystem) would ignore the signals in the parent, popen() equivalents (e.g. runInteractiveProcess) wouldn't, and lower-level functions (e.g. runProcess) would give you a choice.
Unfortunately, there is an inherent conflict between portability and generality, as the Unix and Windows interfaces are substantially different. Unix has separate fork/exec primitives, with the option to execute arbitrary code between the two, whilst Windows has a single primitive with a fixed set of options.
Essentially, I'm not sure that a Windows-compatible runProcess would be sufficiently general to accurately implement both system() and popen() equivalents on Unix. Either system/rawSystem should be implemented using lower-level functions (i.e. not runProcess) or runProcess needs an additional option to control the handling of signals in the child.
Also, my comment regarding the signals being "reset" in the child was inaccurate. system() doesn't reset them in the sense of SIG_DFL. It sets them to SIG_IGN before the fork(), recording their previous handlers. After the fork, it resets them in the child to the values they had upon entry to the system() function (i.e. to the values they had before they were ignored). The effect is as if they had been set to SIG_IGN in the parent after the fork(), but without the potential race condition.
Thus, if they were originally ignored in the parent before system() was entered, they will be ignored in the child. If they were at their defaults (SIG_DFL) before system() was entered, they will be so in the child. If they had been set to specific handlers, system() will restore those handlers in the child, but then execve() will reset them to SIG_DFL, as the handler functions won't exist after the execve().