Currently SBCL runs RUN-PRGORAM child processes in their own process
groups, on the same controlling terminal (if any) that SBCL has.
So, running a terminal-aware program like Bash with it hangs, because
Bash asks for the terminal with tcsetpgrp, which signals SIGTTOU --
which SBCL's SIGCHLD handler doesn't deal with especially.
As far as I can tell, there are three approaches we can take:
1. We run the child in our process group. Pro: simple, clean
semantics. Con: "terminal signals" like SIGINT, SIGSTP, SIGTTOU,
SIGTTIN, etc, typically get delivered to the process group -- so
SBCL will get them too.
(As far as I can tell, this is the motivation for running
child processes in separate process groups.)
2. We run the child in a separate process group, letting it share
our terminal. Pro: child can be stopped without affecting SBCL.
Con: we need to implement terminal management and job control,
responding to SIGTTIN and SIGTTOU correctly, and the it seems
that correct semantics will be different depending on whether
SBCL is the foreground or the background process, and whether it
is being run from eg. a shell or make.
(Currently we take this approach half-heartedly: we set up the
process group, but don't do any terminal management or job
3. We run the child in a separate process group and session, without
a controlling terminal. Pro: semantics independent of SBCL's
backround/foreground status, no need to implement job control,
SIGSTOP to child doesn't affect us. Con: even if the child
behaves as if it has the foreground, ^C and ^Z will be delivered
to SBCL, not the child.
(Actually, we to this currently on HPUX, assuming we still build
I think 3. is clearly the right thing to do for :WAIT NIL. :WAIT T
processess are a lot trickier.
I have a 90% job-control implementation (for 2.), but I'd rather not
go that route, as in the process of doing it I was really appalled by
the semantics of it.
I think the simple and arguably sane thing for :WAIT T would be 1.,
but with waitpid for the process (instead of wait3 for any child), and
ignoring a few crucial the signals during the wait. (Doing the waitpid
instead of wait3 has the additional benefit of matching the Win32
semantics, but that seems rather less important.)
So, the question: which signals to ignore or otherwise take special
* SIGINT: ignore.
* SIGSTP: ignore. Let waitpid WUNTRACED catch stopped children, and
add a PROCESS-CONTINUE function that continues a stopped child and
resumes a "foreground" wait for :WAIT T processes.
* SIGALRM: don't deal with this directly, but if RUN-PROGRAM :WAIT T
unwinds before the process has finished, SIGHUP it.
Anything else? (Before you say SIGTTIN or SIGTTOU, think again: if we
deal with them we need to deal with the whole terminal management
-- Nikodemus Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs."