delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2004/09/16/14:44:38

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
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" <pierre DOT humblet AT ieee DOT org>
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>

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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019