[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] 3.0: Unimplemented WCONTINUED causing a hang

From: Maciej W. Rozycki
Subject: [PATCH] 3.0: Unimplemented WCONTINUED causing a hang
Date: Tue, 17 May 2005 18:38:59 +0100 (BST)


 I've triggered this problem using glibc 2.3.5 and Linux 2.4.29 with a 
mips64el-linux-gnu host.  With such a configuration bash 3.0 (release, 
patch level 16) hangs in the interactive mode when a command resulting in 
forking a subprocess in the foreground concludes.  I've tracked it down to 
the WCONTINUED waitpid() flag (for this host it gets actually translated 
to the wait4() syscall) that's used by bash, but unimplemented by this 
version of Linux (it's only implemented by Linux 2.6.x and actually not 
processor-dependent).  As a result the syscall (and its wrapping library 
function) returns unsuccessfully with the EINVAL error code.  A search of 
the net reveals this error code for invalid options for the function 
(syscall) is not specific to Linux, so it should be safe to be used here.

 I've implemented a fix as follows which works for me.  If unimplemented 
the WCONTINUED flag is tried only once -- this helps performance.  Note 
that glibc cannot determine which version of Linux it's going to be run 
on, so it cannot define the flag in its headers conditionally.

2005-05-17  Maciej W. Rozycki  <address@hidden>

        * jobs.c (waitchld): Detect WCONTINUED being unimplemented and
        stop using it if so.

 Please apply.


diff -up --recursive --new-file bash-3.0.macro/jobs.c bash-3.0/jobs.c
--- bash-3.0.macro/jobs.c       2004-04-23 20:28:25.000000000 +0000
+++ bash-3.0/jobs.c     2005-05-16 03:55:32.000000000 +0000
@@ -2467,6 +2467,7 @@ waitchld (wpid, block)
      pid_t wpid;
      int block;
+  static int wcontinued = WCONTINUED;
   WAIT status;
   PROCESS *child;
   pid_t pid;
@@ -2480,12 +2481,19 @@ waitchld (wpid, block)
       /* We don't want to be notified about jobs stopping if job control
         is not active.  XXX - was interactive_shell instead of job_control */
       waitpid_flags = (job_control && subshell_environment == 0)
-                       ? (WUNTRACED|WCONTINUED)
+                       ? (WUNTRACED|wcontinued)
                        : 0;
       if (sigchld || block == 0)
        waitpid_flags |= WNOHANG;
       pid = WAITPID (-1, &status, waitpid_flags);
+      /* WCONTINUED may not always be accepted. */
+      if (wcontinued && pid < 0 && errno == EINVAL)
+       {
+         wcontinued = 0;
+         continue;     /* jumps right to the test */
+       }
       /* The check for WNOHANG is to make sure we decrement sigchld only
         if it was non-zero before we called waitpid. */
       if (sigchld > 0 && (waitpid_flags & WNOHANG))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]