Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <4149DF06.3454B2D3@ieee.org> Date: Thu, 16 Sep 2004 14:44:22 -0400 From: "Pierre A. Humblet" Reply-To: pierre DOT humblet AT ieee DOT org MIME-Version: 1.0 To: chet AT po DOT cwru DOT edu CC: cygwin AT cygwin DOT com, ronald AT landheer DOT com Subject: Re: Bash returns incorrect process status References: <41499B4A DOT 207AC15F AT ieee DOT org> <040916151300 DOT AA27319 DOT SM AT caleb DOT ins DOT cwru DOT edu> <20040916154409 DOT GC681 AT trixie DOT casa DOT cgf DOT cx> <040916172728 DOT AA27372 DOT SM AT caleb DOT ins DOT cwru DOT edu> Content-Type: multipart/mixed; boundary="------------D7E7F3AF6EF7E0F3E1BA47E3" --------------D7E7F3AF6EF7E0F3E1BA47E3 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Chet Ramey wrote: > > > >POSIX shells are required to remember at least CHILD_MAX (but > > >optionally more) process statuses. There is a gray area about whether > > >or not the user can query the status of those processes, implying that > > >once the status of a background or foreground job has been reported, > > >its status, and the status of its constituent processes, can be > > >discarded, but those rules are hard to decipher. > > > > Are you saying that waitpid should be able to return the status of an > > exited process when it is called repeatedly? I've never seen anything > > like that. I thought that once you'd done a wait the process was > > unzombified, it goes away, and it is unavailable for future querying. > > No. The portion of the POSIX spec describing the shell's behavior is > independent of the exact function used to query a process's status. It > says the shell has to remember. It doesn't mention waitpid(), nor does > it need to. > > You're assuming that the shell just does a waitpid() whenever it needs to > get a particular process's status. No shell does it that way. In practice, when does bash need to get a process status on a per pid (and not per job) basis? FWIW, attached is a patch to bash that may improve its behavior on Cygwin. The idea is that when a new process is stored in the memory array, any existing process with the same pid is marked "reused". "reused" processes are never considered when searching for a process by pid. They are still still available, e.g. to get the status of processes in a job. It's a proof of principle code, not meant to be efficient. It can still print a debug message on stderr. Pierre --------------D7E7F3AF6EF7E0F3E1BA47E3 Content-Type: text/plain; charset=us-ascii; name="jobs.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="jobs.diff" --- jobs.h.orig 2002-01-17 12:35:11.000000000 -0500 +++ jobs.h 2004-09-16 14:11:02.107380800 -0400 @@ -55,6 +55,7 @@ typedef struct process { WAIT status; /* The status of this command as returned by wait. */ int running; /* Non-zero if this process is running. */ char *command; /* The particular program that is running. */ + int reused; } PROCESS; /* PRUNNING really means `not exited' */ --- jobs.c.orig 2002-05-09 11:56:20.000000000 -0400 +++ jobs.c 2004-09-16 14:01:25.478228800 -0400 @@ -737,7 +737,35 @@ add_process (name, pid) char *name; pid_t pid; { - PROCESS *t, *p; + PROCESS *t, *p, * p_start; + register int i; + + for (i = -1; i < job_slots; i++) + { + if (i < 0) + { + if (!(p = the_pipeline)) + continue; + } + else if (jobs[i]) + p = jobs[i]->pipe; + else + continue; + + p_start = p; + do + { + if (p->pid == pid && !p->reused) + { + p->reused = 1; + fprintf(stderr, "Found old pid %d in job %d\n", pid, i); + goto done; + } + p = p->next; + } + while (p != p_start); + } + done: t = (PROCESS *)xmalloc (sizeof (PROCESS)); t->next = the_pipeline; @@ -745,6 +773,7 @@ add_process (name, pid) WSTATUS (t->status) = 0; t->running = PS_RUNNING; t->command = name; + t->reused = 0; the_pipeline = t; if (t->next == 0) @@ -902,12 +931,11 @@ find_pipeline (pid, running_only, jobp) do { /* Return it if we found it. */ - if (p->pid == pid) + if (p->pid == pid && !p->reused) { if ((running_only && PRUNNING(p)) || (running_only == 0)) return (p); } - p = p->next; } while (p != the_pipeline); @@ -937,7 +965,7 @@ find_job (pid, running_only) do { - if (p->pid == pid) + if (p->pid == pid && !p->reused) { if ((running_only && PRUNNING(p)) || (running_only == 0)) return (i); --------------D7E7F3AF6EF7E0F3E1BA47E3 Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --------------D7E7F3AF6EF7E0F3E1BA47E3--