1
0
Fork 0
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:
Peter Stephenson 2008-05-02 22:48:58 +00:00
parent a8854f71eb
commit a9ad660bd3
4 changed files with 81 additions and 45 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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:

View File

@ -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 */