Re: [PATCH] flock: fix hang when parent ignores SIGCHLD

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

 



On Mon, Dec 07, 2009 at 06:05:10AM -0500, Mike Frysinger wrote:
> If flock is executed from a process which has set SIGCHLD to SIG_IGN, then
> flock will eat cpu and hang indefinitely if given a command to execute.

 Good catch.

 I think the core of the problem is pretty naive usage of waitpid() in
 flock.c:

     do {
         w = waitpid(f, &status, 0);
     } while ( w != f );

 this code does not expect any errors, but waitpid() can return -1 (for 
 example for SIG_IGN). I have added some check to this code.

> So before we fork(), make sure to set SIGCHLD handling back to the default
> so that the later waitpid() doesn't freak out on us.

 We can check for ECHILD errno, but your suggestion is better because
 it allows to catch the status value from the child process.
   
 Applied (see below), thanks. 

    Karel


>From 60cd48bd1425610fbdcdb20249210c7f986cb31d Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@xxxxxxxxxx>
Date: Mon, 7 Dec 2009 15:18:17 +0100
Subject: [PATCH] flock: fix hang when parent ignores SIGCHLD

If flock is executed from a process which has set SIGCHLD to SIG_IGN, then
flock will eat cpu and hang indefinitely if given a command to execute.
So before we fork(), make sure to set SIGCHLD handling back to the default
so that the later waitpid() doesn't freak out on us.

[kzak@xxxxxxxxxx: - add a check for waitpid() return value]

Signed-off-by: Mike Frysinger <vapier@xxxxxxxxxx>
Signed-off-by: Karel Zak <kzak@xxxxxxxxxx>
---
 sys-utils/flock.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/sys-utils/flock.c b/sys-utils/flock.c
index a53f6d3..75c007c 100644
--- a/sys-utils/flock.c
+++ b/sys-utils/flock.c
@@ -287,6 +287,8 @@ int main(int argc, char *argv[])
   if ( cmd_argv ) {
     pid_t w, f;
 
+    /* Clear any inherited settings */
+    signal(SIGCHLD, SIG_DFL);
     f = fork();
 
     if ( f < 0 ) {
@@ -304,9 +306,15 @@ int main(int argc, char *argv[])
     } else {
       do {
 	w = waitpid(f, &status, 0);
+	if (w == -1 && errno != EINTR)
+	  break;
       } while ( w != f );
 
-      if ( WIFEXITED(status) )
+      if (w == -1) {
+	err = errno;
+	status = EXIT_FAILURE;
+	fprintf(stderr, "%s: waitpid failed: %s\n", program, strerror(err));
+      } else if ( WIFEXITED(status) )
 	status = WEXITSTATUS(status);
       else if ( WIFSIGNALED(status) )
 	status = WTERMSIG(status) + 128;
-- 
1.6.5.2

--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux