Mercurial > hg > xemacs-beta
diff src/process-unix.c @ 369:1d62742628b6 r21-1-14
Import from CVS: tag r21-1-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:01:51 +0200 |
parents | 30d2cfa1092a |
children | cc15677e0335 |
line wrap: on
line diff
--- a/src/process-unix.c Mon Aug 13 11:01:11 2007 +0200 +++ b/src/process-unix.c Mon Aug 13 11:01:51 2007 +0200 @@ -817,17 +817,15 @@ int xforkin = forkin; int xforkout = forkout; - if (!pty_flag) - EMACS_SEPARATE_PROCESS_GROUP (); -#ifdef HAVE_PTYS - else - { /* Disconnect the current controlling terminal, pursuant to making the pty be the controlling terminal of the process. Also put us in our own process group. */ disconnect_controlling_terminal (); +#ifdef HAVE_PTYS + if (pty_flag) + { /* Open the pty connection and make the pty's terminal our controlling terminal. @@ -1289,7 +1287,17 @@ return usid; } -/* send a signal number SIGNO to PROCESS. +/* If the subtty field of the process data is not filled in, do so now. */ +static void +try_to_initialize_subtty (struct unix_process_data *upd) +{ + if (upd->pty_flag + && (upd->subtty == -1 || ! isatty (upd->subtty)) + && STRINGP (upd->tty_name)) + upd->subtty = open ((char *) XSTRING_DATA (upd->tty_name), O_RDWR, 0); +} + +/* Send signal number SIGNO to PROCESS. CURRENT_GROUP means send to the process group that currently owns the terminal being used to communicate with PROCESS. This is used for various commands in shell mode. @@ -1298,70 +1306,18 @@ If we can, we try to signal PROCESS by sending control characters down the pty. This allows us to signal inferiors who have changed - their uid, for which killpg would return an EPERM error. + their uid, for which killpg would return an EPERM error, + or processes running on other machines via remote login. - The method signals an error if the given SIGNO is not valid -*/ + The method signals an error if the given SIGNO is not valid. */ static void unix_kill_child_process (Lisp_Object proc, int signo, int current_group, int nomsg) { - int gid; - int no_pgrp = 0; - int kill_retval; + pid_t pgid = -1; struct Lisp_Process *p = XPROCESS (proc); - - if (!UNIX_DATA(p)->pty_flag) - current_group = 0; - - /* If we are using pgrps, get a pgrp number and make it negative. */ - if (current_group) - { -#ifdef SIGNALS_VIA_CHARACTERS - /* If possible, send signals to the entire pgrp - by sending an input character to it. */ - { - char sigchar = process_signal_char(UNIX_DATA(p)->subtty, signo); - if (sigchar) { - send_process (proc, Qnil, (Bufbyte *) &sigchar, 0, 1); - return; - } - } -#endif /* ! defined (SIGNALS_VIA_CHARACTERS) */ - -#ifdef TIOCGPGRP - /* Get the pgrp using the tty itself, if we have that. - Otherwise, use the pty to get the pgrp. - On pfa systems, saka@pfu.fujitsu.co.JP writes: - "TIOCGPGRP symbol defined in sys/ioctl.h at E50. - But, TIOCGPGRP does not work on E50 ;-P works fine on E60" - His patch indicates that if TIOCGPGRP returns an error, then - we should just assume that p->pid is also the process group id. */ - { - int err; - - err = ioctl ( (UNIX_DATA(p)->subtty != -1 - ? UNIX_DATA(p)->subtty - : UNIX_DATA(p)->infd), TIOCGPGRP, &gid); - -#ifdef pfa - if (err == -1) - gid = - XINT (p->pid); -#endif /* ! defined (pfa) */ - } - if (gid == -1) - no_pgrp = 1; - else - gid = - gid; -#else /* ! defined (TIOCGPGRP ) */ - /* Can't select pgrps on this system, so we know that - the child itself heads the pgrp. */ - gid = - XINT (p->pid); -#endif /* ! defined (TIOCGPGRP ) */ - } - else - gid = - XINT (p->pid); + struct unix_process_data *d = UNIX_DATA (p); switch (signo) { @@ -1378,38 +1334,100 @@ case SIGINT: case SIGQUIT: case SIGKILL: - flush_pending_output (UNIX_DATA(p)->infd); + flush_pending_output (d->infd); break; } - /* If we don't have process groups, send the signal to the immediate - subprocess. That isn't really right, but it's better than any - obvious alternative. */ - if (no_pgrp) + if (! d->pty_flag) + current_group = 0; + + /* If current_group is true, we want to send a signal to the + foreground process group of the terminal our child process is + running on. You would think that would be easy. + + The BSD people invented the TIOCPGRP ioctl to get the foreground + process group of a tty. That, combined with killpg, gives us + what we want. + + However, the POSIX standards people, in their infinite wisdom, + have seen fit to only allow this for processes which have the + terminal as controlling terminal, which doesn't apply to us. + + Sooo..., we have to do something non-standard. The ioctls + TIOCSIGNAL, TIOCSIG, and TIOCSIGSEND send the signal directly on + many systems. POSIX tcgetpgrp(), since it is *documented* as not + doing what we want, is actually less likely to work than the BSD + ioctl TIOCGPGRP it is supposed to obsolete. Sometimes we have to + use TIOCGPGRP on the master end, sometimes the slave end + (probably an AIX bug). So we better get a fd for the slave if we + haven't got it yet. + + Anal operating systems like SGI Irix and Compaq Tru64 adhere + strictly to the letter of the law, so our hack doesn't work. + The following fragment from an Irix header file is suggestive: + + #ifdef __notdef__ + // this is not currently supported + #define TIOCSIGNAL (tIOC|31) // pty: send signal to slave + #endif + + On those systems where none of our tricks work, we just fall back + to the non-current_group behavior and kill the process group of + the child. + */ + if (current_group) { - kill_retval = kill (XINT (p->pid), signo) ? errno : 0; - } - else + try_to_initialize_subtty (d); + +#ifdef SIGNALS_VIA_CHARACTERS + /* If possible, send signals to the entire pgrp + by sending an input character to it. */ { - /* gid may be a pid, or minus a pgrp's number */ -#if defined (TIOCSIGNAL) || defined (TIOCSIGSEND) - if (current_group) + char sigchar = process_signal_char (d->subtty, signo); + if (sigchar) { -#ifdef TIOCSIGNAL - kill_retval = ioctl (UNIX_DATA(p)->infd, TIOCSIGNAL, signo); -#else /* ! defined (TIOCSIGNAL) */ - kill_retval = ioctl (UNIX_DATA(p)->infd, TIOCSIGSEND, signo); -#endif /* ! defined (TIOCSIGNAL) */ + send_process (proc, Qnil, (Bufbyte *) &sigchar, 0, 1); + return; } - else - kill_retval = kill (- XINT (p->pid), signo) ? errno : 0; -#else /* ! (defined (TIOCSIGNAL) || defined (TIOCSIGSEND)) */ - kill_retval = EMACS_KILLPG (-gid, signo) ? errno : 0; -#endif /* ! (defined (TIOCSIGNAL) || defined (TIOCSIGSEND)) */ } +#endif /* SIGNALS_VIA_CHARACTERS */ - if (kill_retval < 0 && errno == EINVAL) - error ("Signal number %d is invalid for this system", signo); +#ifdef TIOCGPGRP + if (pgid == -1) + ioctl (d->infd, TIOCGPGRP, &pgid); /* BSD */ + if (pgid == -1 && d->subtty != -1) + ioctl (d->subtty, TIOCGPGRP, &pgid); /* Only this works on AIX! */ +#endif /* TIOCGPGRP */ + + if (pgid == -1) + { + /* Many systems provide an ioctl to send a signal directly */ +#ifdef TIOCSIGNAL /* Solaris, HP-UX */ + if (ioctl (d->infd, TIOCSIGNAL, signo) != -1) + return; +#endif /* TIOCSIGNAL */ + +#ifdef TIOCSIG /* BSD */ + if (ioctl (d->infd, TIOCSIG, signo) != -1) + return; +#endif /* TIOCSIG */ + } + } /* current_group */ + + if (pgid == -1) + /* Either current_group is 0, or we failed to get the foreground + process group using the trickery above. So we fall back to + sending the signal to the process group of our child process. + Since this is often a shell that ignores signals like SIGINT, + the shell's subprocess is killed, which is the desired effect. + The process group of p->pid is always p->pid, since it was + created as a process group leader. */ + pgid = XINT (p->pid); + + /* Finally send the signal. */ + if (EMACS_KILLPG (pgid, signo) == -1) + error ("kill (%ld, %ld) failed: %s", + (long) pgid, (long) signo, strerror (errno)); } /*