diff options
author | raf <none@none> | 2005-07-20 20:23:03 -0700 |
---|---|---|
committer | raf <none@none> | 2005-07-20 20:23:03 -0700 |
commit | 8e3c57a3c9aa75d7adfa6ee670c67507535df4d4 (patch) | |
tree | c675ad8a85735156fac8046fa642236337045306 | |
parent | 0bfcf696a56550659cdffd7dbc287c3f1abf65f1 (diff) | |
download | illumos-joyent-8e3c57a3c9aa75d7adfa6ee670c67507535df4d4.tar.gz |
6282038 For csh, solaris 10 command form program>`program` never executes. cannot ctrl C out of it either
-rw-r--r-- | usr/src/cmd/csh/sh.proc.c | 26 | ||||
-rw-r--r-- | usr/src/cmd/csh/wait.h | 45 | ||||
-rw-r--r-- | usr/src/cmd/csh/wait3.c | 155 |
3 files changed, 125 insertions, 101 deletions
diff --git a/usr/src/cmd/csh/sh.proc.c b/usr/src/cmd/csh/sh.proc.c index 195d2b07a1..2e4bfc4ea9 100644 --- a/usr/src/cmd/csh/sh.proc.c +++ b/usr/src/cmd/csh/sh.proc.c @@ -1,5 +1,5 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -230,7 +230,29 @@ pjwait(pp) while ((fp = (fp->p_friends)) != pp); if ((jobflags & PRUNNING) == 0) break; - sigpause(sigblock(0) &~ sigmask(SIGCHLD)); + /* + * At this point, csh used to call: + * sigpause(sigblock(0) &~ sigmask(SIGCHLD)); + * expecting to receive a SIGCHLD signal from the + * termination of the child and to invoke the + * signal handler, pchild(), as a result. + * + * However, vfork() now causes a vfork()'d child to + * have all of its active signal handlers reset to + * SIG_DFL, to forstall parent memory corruption due + * to race conditions with signal handling. + * + * If this instance of csh is itself a child of vfork(), + * which can happen when the top-level csh performs a + * command substitution inside an i/o redirection, like: + * /bin/echo foo >`/bin/echo trash` + * then we will never receive SIGCHLD. To accommodate + * this, we wait until one of our children terminates + * (without actually reaping the child) and call the + * SIGCHLD signal handler (pchild()) directly. + */ + if (csh_wait_noreap() > 0) + pchild(); /* simulate receipt of SIGCHLD */ } (void) sigsetmask(omask); if (tpgrp > 0) /* get tty back */ diff --git a/usr/src/cmd/csh/wait.h b/usr/src/cmd/csh/wait.h index 97b3579bc8..95260be9d9 100644 --- a/usr/src/cmd/csh/wait.h +++ b/usr/src/cmd/csh/wait.h @@ -1,6 +1,9 @@ /* - * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + */ + +/* * * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T * All Rights Reserved @@ -22,9 +25,9 @@ */ #ifndef _sys_wait_h -#define _sys_wait_h +#define _sys_wait_h -#include <sys/isa_defs.h> /* included for _LITTLE_ENDIAN define */ +#include <sys/isa_defs.h> /* included for _LITTLE_ENDIAN define */ /* * Structure of the information in the first word returned by both @@ -69,14 +72,14 @@ union wait { } w_S; }; #define w_termsig w_T.w_Termsig -#define w_coredump w_T.w_Coredump -#define w_retcode w_T.w_Retcode -#define w_stopval w_S.w_Stopval -#define w_stopsig w_S.w_Stopsig +#define w_coredump w_T.w_Coredump +#define w_retcode w_T.w_Retcode +#define w_stopval w_S.w_Stopval +#define w_stopsig w_S.w_Stopsig #define WSTOPPED 0177 /* value of s.stopval if process is stopped */ -#define WCONTFLG 0177777 /* value of w.w_status due to SIGCONT, sysV */ +#define WCONTFLG 0177777 /* value of w.w_status due to SIGCONT, sysV */ /* * Option bits for the second argument of wait3. WNOHANG causes the @@ -87,24 +90,14 @@ union wait { * this option is done, it is as though they were still running... nothing * about them is returned. */ -#define WNOHANG 1 /* dont hang in wait */ -#define WUNTRACED 2 /* tell about stopped, untraced children */ +#define WNOHANG 1 /* dont hang in wait */ +#define WUNTRACED 2 /* tell about stopped, untraced children */ -#define WIFSTOPPED(x) ((x).w_stopval == WSTOPPED) -#define WIFSIGNALED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig != 0) -#define WIFEXITED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig == 0) +#define WIFSTOPPED(x) ((x).w_stopval == WSTOPPED) +#define WIFSIGNALED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig != 0) +#define WIFEXITED(x) ((x).w_stopval != WSTOPPED && (x).w_termsig == 0) -#ifdef KERNEL -/* - * Arguments to wait4() system call, included here so it may be called by - * other routines in the kernel - */ -struct wait4_args { - int pid; - union wait *status; - int options; - struct rusage *rusage; -}; -#endif KERNEL +extern pid_t csh_wait3(union wait *w, int options, struct rusage *rp); +extern pid_t csh_wait_noreap(void); -#endif /*!_sys_wait_h*/ +#endif /* _sys_wait_h */ diff --git a/usr/src/cmd/csh/wait3.c b/usr/src/cmd/csh/wait3.c index b2ae68c95a..75c3ce366e 100644 --- a/usr/src/cmd/csh/wait3.c +++ b/usr/src/cmd/csh/wait3.c @@ -1,10 +1,10 @@ /* - * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ +/* All Rights Reserved */ /* * Copyright (c) 1980 Regents of the University of California. @@ -15,9 +15,9 @@ #pragma ident "%Z%%M% %I% %E% SMI" /* - * Compatibility lib for BSD's wait3(). It is not - * binary compatible, since BSD's WNOHANG and WUNTRACED - * carry different #define values. + * Compatibility lib for BSD's wait3(). It is not + * binary compatible, since BSD's WNOHANG and WUNTRACED + * carry different #define values. */ #include <errno.h> #include <sys/types.h> @@ -32,17 +32,17 @@ /* * Since sysV does not support rusage as in BSD, an approximate approach * is: - * ... - * call times - * call waitid - * if ( a child is found ) - * call times again - * rusage ~= diff in the 2 times call - * ... - * + * ... + * call times + * call waitid + * if ( a child is found ) + * call times again + * rusage ~= diff in the 2 times call + * ... + * */ -/* +/* * XXX: There is now a wait3 function in libc which should be used instead * of this local version of wait3. With the addition of a wait3 prototype * in <sys/wait.h> as per the X/Open XPG4v2 specification, compilation of @@ -50,87 +50,96 @@ * version. Using the libc wait3 rather than the local version results in * a failure with csh, however, this version should eventually be dropped * in favor of the libc wait3 with appropriate updates made to sh.proc.c - * to account for the difference in implementation of the local versus + * to account for the difference in implementation of the local versus * the libc versions. This should probably be done as part of an overall * effort to rid csh of local versions of functions now in libc. */ -csh_wait3(status, options, rp) - int *status; - int options; - struct rusage *rp; - +static int wstat(int code, int status); + +pid_t +csh_wait3(int *status, int options, struct rusage *rp) { - struct tms before_tms; - struct tms after_tms; - siginfo_t info; - int error; + struct tms before_tms; + struct tms after_tms; + siginfo_t info; + int error; if (rp) - memset((void *)rp, 0, sizeof(struct rusage)); - memset((void *)&info, 0, sizeof(siginfo_t)); - if ( times(&before_tms) == -1 ) - return (-1); /* errno is set by times() */ + memset((void *)rp, 0, sizeof (struct rusage)); + memset((void *)&info, 0, sizeof (siginfo_t)); + if (times(&before_tms) == -1) + return (-1); /* errno is set by times() */ /* * BSD's wait3() only supports WNOHANG & WUNTRACED */ options |= (WNOHANG|WUNTRACED|WEXITED|WSTOPPED|WTRAPPED|WCONTINUED); - error = waitid(P_ALL, 0, &info, options); - if ( error == 0 ) { - clock_t diffu; /* difference in usertime (ticks) */ - clock_t diffs; /* difference in systemtime (ticks) */ + error = waitid(P_ALL, 0, &info, options); + if (error == 0) { + clock_t diffu; /* difference in usertime (ticks) */ + clock_t diffs; /* difference in systemtime (ticks) */ - if ( (options & WNOHANG) && (info.si_pid == 0) ) - return (0); /* no child found */ + if ((options & WNOHANG) && (info.si_pid == 0)) + return (0); /* no child found */ if (rp) { - if ( times(&after_tms) == -1 ) - return (-1); /* errno set by times() */ - /* - * The system/user time is an approximation only !!! - */ - diffu = after_tms.tms_cutime - before_tms.tms_cutime; - diffs = after_tms.tms_cstime - before_tms.tms_cstime; - rp->ru_utime.tv_sec = diffu/HZ; - rp->ru_utime.tv_usec = (diffu % HZ) / HZ * 1000000; - rp->ru_stime.tv_sec = diffs/HZ; - rp->ru_stime.tv_usec = (diffs % HZ) / HZ * 1000000; + if (times(&after_tms) == -1) + return (-1); /* errno set by times() */ + /* + * The system/user time is an approximation only !!! + */ + diffu = after_tms.tms_cutime - before_tms.tms_cutime; + diffs = after_tms.tms_cstime - before_tms.tms_cstime; + rp->ru_utime.tv_sec = diffu/HZ; + rp->ru_utime.tv_usec = (diffu % HZ) / HZ * 1000000; + rp->ru_stime.tv_sec = diffs/HZ; + rp->ru_stime.tv_usec = (diffs % HZ) / HZ * 1000000; } - *status = wstat(info.si_code, info.si_status); - return (info.si_pid); + *status = wstat(info.si_code, info.si_status); + return (info.si_pid); - } else { - return (-1); /* error number is set by waitid() */ - } + } else { + return (-1); /* error number is set by waitid() */ + } } /* * Convert the status code to old style wait status */ -wstat(code, status) - int code; - int status; +static int +wstat(int code, int status) { - register stat = (status & 0377); - - switch (code) { - case CLD_EXITED: - stat <<= 8; - break; - case CLD_DUMPED: - stat |= WCOREFLG; - break; - case CLD_KILLED: - break; - case CLD_TRAPPED: - case CLD_STOPPED: - stat <<= 8; - stat |= WSTOPFLG; - break; + int stat = (status & 0377); + + switch (code) { + case CLD_EXITED: + stat <<= 8; + break; + case CLD_DUMPED: + stat |= WCOREFLG; + break; + case CLD_KILLED: + break; + case CLD_TRAPPED: + case CLD_STOPPED: + stat <<= 8; + stat |= WSTOPFLG; + break; case CLD_CONTINUED: - stat = WCONTFLG; - break; - } - return (stat); + stat = WCONTFLG; + break; + } + return (stat); +} + +pid_t +csh_wait_noreap(void) +{ + siginfo_t info; + + if (waitid(P_ALL, 0, &info, + WEXITED | WTRAPPED | WSTOPPED | WCONTINUED | WNOWAIT) != 0) + return (-1); + return (info.si_pid); } |