mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-05-27 10:26:05 +02:00
users/12812: fix hang with confusion over process numbers
This commit is contained in:
parent
a8854f71eb
commit
a9ad660bd3
|
@ -1,3 +1,10 @@
|
|||
2008-05-02 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* users/12815: Src/jobs.c, Src/signals.c, Src/zsh.h:
|
||||
fix bug that a previously defunct process could be taken as a
|
||||
recently terminated process that needed marking as done, hence
|
||||
causing the shell to wait for ever for the newly exited process.
|
||||
|
||||
2008-05-01 Peter Stephenson <pws@csr.com>
|
||||
|
||||
* 24900: Doc/Zsh/zle.yo, Src/Zle/zle_hist.c: add
|
||||
|
|
|
@ -153,6 +153,15 @@ findproc(pid_t pid, Job *jptr, Process *pptr, int aux)
|
|||
|
||||
for (i = 1; i <= maxjob; i++)
|
||||
{
|
||||
/*
|
||||
* We are only interested in jobs with processes still
|
||||
* marked as live. Careful in case there's an identical
|
||||
* process number in a job we haven't quite got around
|
||||
* to deleting.
|
||||
*/
|
||||
if (jobtab[i].stat & STAT_DONE)
|
||||
continue;
|
||||
|
||||
for (pn = aux ? jobtab[i].auxprocs : jobtab[i].procs;
|
||||
pn; pn = pn->next)
|
||||
if (pn->pid == pid) {
|
||||
|
|
|
@ -408,15 +408,21 @@ zhandler(int sig)
|
|||
signal_process(sig);
|
||||
|
||||
sigfillset(&newmask);
|
||||
oldmask = signal_block(newmask); /* Block all signals temporarily */
|
||||
/* Block all signals temporarily */
|
||||
oldmask = signal_block(newmask);
|
||||
|
||||
#if defined(NO_SIGNAL_BLOCKING)
|
||||
do_jump = suspend_longjmp; /* do we need to longjmp to signal_suspend */
|
||||
suspend_longjmp = 0; /* In case a SIGCHLD somehow arrives */
|
||||
/* do we need to longjmp to signal_suspend */
|
||||
do_jump = suspend_longjmp;
|
||||
/* In case a SIGCHLD somehow arrives */
|
||||
suspend_longjmp = 0;
|
||||
|
||||
if (sig == SIGCHLD) { /* Traps can cause nested signal_suspend() */
|
||||
if (do_jump)
|
||||
jump_to = suspend_jmp_buf; /* Copy suspend_jmp_buf */
|
||||
/* Traps can cause nested signal_suspend() */
|
||||
if (sig == SIGCHLD) {
|
||||
if (do_jump) {
|
||||
/* Copy suspend_jmp_buf */
|
||||
jump_to = suspend_jmp_buf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -425,30 +431,36 @@ zhandler(int sig)
|
|||
int temp_rear = ++queue_rear % MAX_QUEUE_SIZE;
|
||||
|
||||
DPUTS(temp_rear == queue_front, "BUG: signal queue full");
|
||||
if (temp_rear != queue_front) { /* Make sure it's not full (extremely unlikely) */
|
||||
queue_rear = temp_rear; /* ok, not full, so add to queue */
|
||||
signal_queue[queue_rear] = sig; /* save signal caught */
|
||||
signal_mask_queue[queue_rear] = oldmask; /* save current signal mask */
|
||||
/* Make sure it's not full (extremely unlikely) */
|
||||
if (temp_rear != queue_front) {
|
||||
/* ok, not full, so add to queue */
|
||||
queue_rear = temp_rear;
|
||||
/* save signal caught */
|
||||
signal_queue[queue_rear] = sig;
|
||||
/* save current signal mask */
|
||||
signal_mask_queue[queue_rear] = oldmask;
|
||||
}
|
||||
signal_reset(sig);
|
||||
return;
|
||||
}
|
||||
|
||||
signal_setmask(oldmask); /* Reset signal mask, signal traps ok now */
|
||||
/* Reset signal mask, signal traps ok now */
|
||||
signal_setmask(oldmask);
|
||||
|
||||
switch (sig) {
|
||||
case SIGCHLD:
|
||||
|
||||
/* keep WAITING until no more child processes to reap */
|
||||
for (;;)
|
||||
cont: {
|
||||
int old_errno = errno; /* save the errno, since WAIT may change it */
|
||||
for (;;) {
|
||||
/* save the errno, since WAIT may change it */
|
||||
int old_errno = errno;
|
||||
int status;
|
||||
Job jn;
|
||||
Process pn;
|
||||
pid_t pid;
|
||||
pid_t pid;
|
||||
pid_t *procsubpid = &cmdoutpid;
|
||||
int *procsubval = &cmdoutval;
|
||||
int cont = 0;
|
||||
struct execstack *es = exstack;
|
||||
|
||||
/*
|
||||
|
@ -471,8 +483,8 @@ zhandler(int sig)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
if (!pid) /* no more children to reap */
|
||||
break;
|
||||
if (!pid) /* no more children to reap */
|
||||
break;
|
||||
|
||||
/* check if child returned was from process substitution */
|
||||
for (;;) {
|
||||
|
@ -483,7 +495,8 @@ zhandler(int sig)
|
|||
else
|
||||
*procsubval = WEXITSTATUS(status);
|
||||
get_usage();
|
||||
goto cont;
|
||||
cont = 1;
|
||||
break;
|
||||
}
|
||||
if (!es)
|
||||
break;
|
||||
|
@ -491,16 +504,22 @@ zhandler(int sig)
|
|||
procsubval = &es->cmdoutval;
|
||||
es = es->next;
|
||||
}
|
||||
if (cont)
|
||||
continue;
|
||||
|
||||
/* check for WAIT error */
|
||||
if (pid == -1) {
|
||||
if (errno != ECHILD)
|
||||
zerr("wait failed: %e", errno);
|
||||
errno = old_errno; /* WAIT changed errno, so restore the original */
|
||||
break;
|
||||
}
|
||||
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. */
|
||||
/*
|
||||
* Find the process and job containing this pid and
|
||||
* update it.
|
||||
*/
|
||||
if (findproc(pid, &jn, &pn, 0)) {
|
||||
#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
|
||||
struct timezone dummy_tz;
|
||||
|
@ -517,11 +536,12 @@ zhandler(int sig)
|
|||
} 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.
|
||||
* will get added on to the next found process that
|
||||
* terminates.
|
||||
*/
|
||||
get_usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SIGHUP:
|
||||
|
|
36
Src/zsh.h
36
Src/zsh.h
|
@ -857,24 +857,24 @@ struct job {
|
|||
struct ttyinfo *ty; /* the modes specified by STTY */
|
||||
};
|
||||
|
||||
#define STAT_CHANGED (1<<0) /* status changed and not reported */
|
||||
#define STAT_STOPPED (1<<1) /* all procs stopped or exited */
|
||||
#define STAT_TIMED (1<<2) /* job is being timed */
|
||||
#define STAT_DONE (1<<3) /* job is done */
|
||||
#define STAT_LOCKED (1<<4) /* shell is finished creating this job, */
|
||||
/* may be deleted from job table */
|
||||
#define STAT_NOPRINT (1<<5) /* job was killed internally, */
|
||||
/* we don't want to show that */
|
||||
#define STAT_INUSE (1<<6) /* this job entry is in use */
|
||||
#define STAT_SUPERJOB (1<<7) /* job has a subjob */
|
||||
#define STAT_SUBJOB (1<<8) /* job is a subjob */
|
||||
#define STAT_WASSUPER (1<<9) /* was a super-job, sub-job needs to be */
|
||||
/* deleted */
|
||||
#define STAT_CURSH (1<<10) /* last command is in current shell */
|
||||
#define STAT_NOSTTY (1<<11) /* the tty settings are not inherited */
|
||||
/* from this job when it exits. */
|
||||
#define STAT_ATTACH (1<<12) /* delay reattaching shell to tty */
|
||||
#define STAT_SUBLEADER (1<<13) /* is super-job, but leader is sub-shell */
|
||||
#define STAT_CHANGED (0x0001) /* status changed and not reported */
|
||||
#define STAT_STOPPED (0x0002) /* all procs stopped or exited */
|
||||
#define STAT_TIMED (0x0004) /* job is being timed */
|
||||
#define STAT_DONE (0x0008) /* job is done */
|
||||
#define STAT_LOCKED (0x0010) /* shell is finished creating this job, */
|
||||
/* may be deleted from job table */
|
||||
#define STAT_NOPRINT (0x0020) /* job was killed internally, */
|
||||
/* we don't want to show that */
|
||||
#define STAT_INUSE (0x0040) /* this job entry is in use */
|
||||
#define STAT_SUPERJOB (0x0080) /* job has a subjob */
|
||||
#define STAT_SUBJOB (0x0100) /* job is a subjob */
|
||||
#define STAT_WASSUPER (0x0200) /* was a super-job, sub-job needs to be */
|
||||
/* deleted */
|
||||
#define STAT_CURSH (0x0400) /* last command is in current shell */
|
||||
#define STAT_NOSTTY (0x0800) /* the tty settings are not inherited */
|
||||
/* from this job when it exits. */
|
||||
#define STAT_ATTACH (0x1000) /* delay reattaching shell to tty */
|
||||
#define STAT_SUBLEADER (0x2000) /* is super-job, but leader is sub-shell */
|
||||
|
||||
#define SP_RUNNING -1 /* fake status for jobs currently running */
|
||||
|
||||
|
|
Loading…
Reference in New Issue