summaryrefslogtreecommitdiff
path: root/Src/signals.c
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2010-08-22 20:08:57 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2010-08-22 20:08:57 +0000
commitc7ff1b79ddcca49bf4585b042f245bb69603f4d8 (patch)
tree9c7e3050f072461f5f1d3c999a9da093d7221468 /Src/signals.c
parent059c8dede666e4b7698f141687e67441c469541e (diff)
downloadzsh-c7ff1b79ddcca49bf4585b042f245bb69603f4d8.tar.gz
zsh-c7ff1b79ddcca49bf4585b042f245bb69603f4d8.zip
28179, users/15314, users/15310, users/15200:
various job and process control fixes
Diffstat (limited to 'Src/signals.c')
-rw-r--r--Src/signals.c229
1 files changed, 125 insertions, 104 deletions
diff --git a/Src/signals.c b/Src/signals.c
index 74aeadde7..49e5e6379 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -400,6 +400,129 @@ signal_suspend(UNUSED(int sig), int wait_cmd)
/**/
int last_signal;
+/*
+ * Wait for any processes that have changed state.
+ *
+ * The main use for this is in the SIGCHLD handler. However,
+ * we also use it to pick up status changes of jobs when
+ * updating jobs.
+ */
+/**/
+void
+wait_for_processes(void)
+{
+ /* keep WAITING until no more child processes to reap */
+ for (;;) {
+ /* save the errno, since WAIT may change it */
+ int old_errno = errno;
+ int status;
+ Job jn;
+ Process pn;
+ pid_t pid;
+ pid_t *procsubpid = &cmdoutpid;
+ int *procsubval = &cmdoutval;
+ int cont = 0;
+ struct execstack *es = exstack;
+
+ /*
+ * Reap the child process.
+ * If we want usage information, we need to use wait3.
+ */
+#if defined(HAVE_WAIT3) || defined(HAVE_WAITPID)
+# ifdef WCONTINUED
+# define WAITFLAGS (WNOHANG|WUNTRACED|WCONTINUED)
+# else
+# define WAITFLAGS (WNOHANG|WUNTRACED)
+# endif
+#endif
+#ifdef HAVE_WAIT3
+# ifdef HAVE_GETRUSAGE
+ struct rusage ru;
+
+ pid = wait3((void *)&status, WAITFLAGS, &ru);
+# else
+ pid = wait3((void *)&status, WAITFLAGS, NULL);
+# endif
+#else
+# ifdef HAVE_WAITPID
+ pid = waitpid(-1, &status, WAITFLAGS);
+# else
+ pid = wait(&status);
+# endif
+#endif
+
+ if (!pid) /* no more children to reap */
+ break;
+
+ /* check if child returned was from process substitution */
+ for (;;) {
+ if (pid == *procsubpid) {
+ *procsubpid = 0;
+ if (WIFSIGNALED(status))
+ *procsubval = (0200 | WTERMSIG(status));
+ else
+ *procsubval = WEXITSTATUS(status);
+ use_cmdoutval = 1;
+ get_usage();
+ cont = 1;
+ break;
+ }
+ if (!es)
+ break;
+ procsubpid = &es->cmdoutpid;
+ procsubval = &es->cmdoutval;
+ es = es->next;
+ }
+ if (cont)
+ continue;
+
+ /* check for WAIT error */
+ if (pid == -1) {
+ if (errno != ECHILD)
+ zerr("wait failed: %e", errno);
+ /* WAIT changed errno, so restore the original */
+ errno = old_errno;
+ break;
+ }
+
+ /*
+ * Find the process and job containing this pid and
+ * update it.
+ */
+ pn = NULL;
+ if (findproc(pid, &jn, &pn, 0)) {
+#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
+ struct timezone dummy_tz;
+ gettimeofday(&pn->endtime, &dummy_tz);
+ pn->status = status;
+ pn->ti = ru;
+#else
+ update_process(pn, status);
+#endif
+ update_job(jn);
+ } else if (findproc(pid, &jn, &pn, 1)) {
+ pn->status = status;
+ update_job(jn);
+ } else {
+ /* If not found, update the shell record of time spent by
+ * children in sub processes anyway: otherwise, this
+ * will get added on to the next found process that
+ * terminates.
+ */
+ get_usage();
+ }
+ /*
+ * Remember the status associated with $!, so we can
+ * wait for it even if it's exited. This value is
+ * only used if we can't find the PID in the job table,
+ * so it doesn't matter that the value we save here isn't
+ * useful until the process has exited.
+ */
+ if (pn != NULL && pid == lastpid && lastpid_status != -1L)
+ lastpid_status = lastval2;
+ }
+}
+
/* the signal handler */
/**/
@@ -458,110 +581,7 @@ zhandler(int sig)
switch (sig) {
case SIGCHLD:
-
- /* keep WAITING until no more child processes to reap */
- for (;;) {
- /* save the errno, since WAIT may change it */
- int old_errno = errno;
- int status;
- Job jn;
- Process pn;
- pid_t pid;
- pid_t *procsubpid = &cmdoutpid;
- int *procsubval = &cmdoutval;
- int cont = 0;
- struct execstack *es = exstack;
-
- /*
- * Reap the child process.
- * If we want usage information, we need to use wait3.
- */
-#ifdef HAVE_WAIT3
-# ifdef HAVE_GETRUSAGE
- struct rusage ru;
-
- pid = wait3((void *)&status, WNOHANG|WUNTRACED, &ru);
-# else
- pid = wait3((void *)&status, WNOHANG|WUNTRACED, NULL);
-# endif
-#else
-# ifdef HAVE_WAITPID
- pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
-# else
- pid = wait(&status);
-# endif
-#endif
-
- if (!pid) /* no more children to reap */
- break;
-
- /* check if child returned was from process substitution */
- for (;;) {
- if (pid == *procsubpid) {
- *procsubpid = 0;
- if (WIFSIGNALED(status))
- *procsubval = (0200 | WTERMSIG(status));
- else
- *procsubval = WEXITSTATUS(status);
- use_cmdoutval = 1;
- get_usage();
- cont = 1;
- break;
- }
- if (!es)
- break;
- procsubpid = &es->cmdoutpid;
- procsubval = &es->cmdoutval;
- es = es->next;
- }
- if (cont)
- continue;
-
- /* check for WAIT error */
- if (pid == -1) {
- if (errno != ECHILD)
- zerr("wait failed: %e", errno);
- /* WAIT changed errno, so restore the original */
- errno = old_errno;
- break;
- }
-
- /*
- * Find the process and job containing this pid and
- * update it.
- */
- pn = NULL;
- if (findproc(pid, &jn, &pn, 0)) {
-#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
- struct timezone dummy_tz;
- gettimeofday(&pn->endtime, &dummy_tz);
- pn->status = status;
- pn->ti = ru;
-#else
- update_process(pn, status);
-#endif
- update_job(jn);
- } else if (findproc(pid, &jn, &pn, 1)) {
- pn->status = status;
- update_job(jn);
- } else {
- /* If not found, update the shell record of time spent by
- * children in sub processes anyway: otherwise, this
- * will get added on to the next found process that
- * terminates.
- */
- get_usage();
- }
- /*
- * Remember the status associated with $!, so we can
- * wait for it even if it's exited. This value is
- * only used if we can't find the PID in the job table,
- * so it doesn't matter that the value we save here isn't
- * useful until the process has exited.
- */
- if (pn != NULL && pid == lastpid && lastpid_status != -1L)
- lastpid_status = lastval2;
- }
+ wait_for_processes();
break;
case SIGHUP:
@@ -580,6 +600,7 @@ zhandler(int sig)
breaks = loops;
errflag = 1;
inerrflush();
+ check_cursh_sig(SIGINT);
}
}
break;