This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
[Probably you've figured this all out now on your own, but...] > guile > guile> (system "xterm &") > guile> [Hit Ctrl-C] > > --> the xterm dies -- apparently because the shell gets a SIGINT and > the shell terminates thus causing the xterm to exit. But: > > guile > guile> (system "xlogo &") > guile> [Hit Ctrl-C] > > --> xlogo lives on. Here's what's going on. Both xlogo and xterm are in the same process group as Guile. All signals generated from the terminal --- things like SIGINT (usually C-c), SIGTSTP (usually C-z), SIGQUIT (usually C-\) --- get sent to the terminal's current process group. So when you hit C-c, guile, xterm, and xlogo all get SIGINT. However, as you can verify by sending these signals to the processes individually by hand from another window, Guile handles SIGINT, xlogo ignores it, and xterm exits. SCWM is really acting like a little shell. I think it should put the programs it spawns in their own process groups. You may need something like this: (define (background-system command) (let ((child-pid (primitive-fork))) (if (zero? child-pid) ;; Okay, we're the child process. We need to catch any and ;; all errors and exit, or else we'll end up with two Guile ;; repls trying to read from the same terminal. (begin (catch #t (lambda () ;; Put ourselves in our own process group. (setpgid (getpid) (getpid)) ;; Try to execute the user's command. (execl "/bin/sh" "sh" "-c" command)) (lambda args #f)) ;; If we return from the exec for any reason, it means it failed. (quit 1)) ;; Okay, we're the parent process. Return the child pid, in ;; case we want to wait for it at some point in the future. child-pid))) So now: guile> (background-system "xterm") 3489 guile> (background-system "xlogo") 3515 guile> ERROR: User interrupt ABORT: (signal) guile> ERROR: User interrupt ABORT: (signal) guile> Both xterm and xlogo remain live. Note that you do want to wait for those processes periodically: ;;; I quit the xterm: guile> (waitpid -1 WNOHANG) (3489 . 0) ;; pid and exit status ;;; I kill the xlogo's X connection, and then: guile> (waitpid -1 WNOHANG) (3515 . 256) ;; pid and a non-zero exit status ;;; What does "256" mean? guile> (status:exit-val 256) 1 ;;; Try waiting again, even though no children have died: guile> (waitpid -1 WNOHANG) ERROR: In procedure waitpid in expression (waitpid -1 WNOHANG): ERROR: No child processes ABORT: (system-error) guile> The error handling in background-system should be improved: if the child process gets an error, it should print that to its stderr, not swallow it. Otherwise, you could get pretty frustrated...