summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorraf <none@none>2005-07-20 20:23:03 -0700
committerraf <none@none>2005-07-20 20:23:03 -0700
commit8e3c57a3c9aa75d7adfa6ee670c67507535df4d4 (patch)
treec675ad8a85735156fac8046fa642236337045306
parent0bfcf696a56550659cdffd7dbc287c3f1abf65f1 (diff)
downloadillumos-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.c26
-rw-r--r--usr/src/cmd/csh/wait.h45
-rw-r--r--usr/src/cmd/csh/wait3.c155
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);
}