bin/90334: /bin/sh trap problem

Maxim Konovalov maxim at macomnet.ru
Tue Dec 13 11:00:19 PST 2005


The following reply was made to PR bin/90334; it has been noted by GNATS.

From: Maxim Konovalov <maxim at macomnet.ru>
To: Dmitriy Kirhlarov <dkirhlarov at oilspace.com>
Cc: bug-followup at freebsd.org, kst at oilspace.com
Subject: Re: bin/90334: /bin/sh trap problem
Date: Tue, 13 Dec 2005 21:51:01 +0300 (MSK)

 [...]
 > >Description:
 > 	on FreeBSD 5.* and FreeBSD 6.* sh scripts hanging with high
 > 	CPU load, when SIGCHLD used.
 > 	problem not present on 4-STABLE
 > >How-To-Repeat:
 > 	run simple script
 > ---
 > 	#!/bin/sh
 > 	trap "" 20
 > 	var=`echo anytext | sed 's/text/any/'`
 > ---
 
 Yep, SIG_IGN as action for SIGCHLD works differ on RELENG_4 and
 post-RELENG_4.  On post-RELENG_4 we can safely SIG_IGN SIGCHLD and the
 kernel will G/C zombies for us.  From signal(3):
 
 % If a process explicitly specifies SIG_IGN as the action for the
 % signal SIGCHLD, the system will not create zombie processes when
 % children of the calling process exit.  As a consequence, the system
 % will discard the exit status from the child processes.  If the
 % calling process subsequently issues a call to wait(2) or equivalent,
 % it will block until all of the calling process's children terminate,
 % and then return a value of -1 with errno set to ECHILD.
 
 'trap "" 20' sets SIG_IGN signal handler for SIGCHLD and we are
 getting ECHILD in jobs.c::waitproc() again and again and fall to the
 following endless loop in jobs.c::waitforjob():
 
 %%%
   865           while (jp->state == 0)
   866                   if (dowait(1, jp) == -1)
   867                           dotrap();
 %%%
 
 There are two patches for the problem:
 
 1/ Mine, if user sets an empty trap for SIGCHLD, use the default
 signal handler:
 
 Index: trap.c
 ===================================================================
 RCS file: /home/ncvs/src/bin/sh/trap.c,v
 retrieving revision 1.31
 diff -u -r1.31 trap.c
 --- trap.c	8 Dec 2005 20:08:36 -0000	1.31
 +++ trap.c	13 Dec 2005 18:18:07 -0000
 @@ -238,6 +238,8 @@
  		action = S_CATCH;
  	else
  		action = S_IGN;
 +	if (action == S_IGN && signo == SIGCHLD)
 +		action = S_DFL;
  	if (action == S_DFL) {
  		switch (signo) {
  		case SIGINT:
 %%%
 
 2/ By your co-worker, Konstantin Stepanenkov, break an endless loop if
 we get ECHILD:
 
 Index: jobs.c
 ===================================================================
 RCS file: /home/ncvs/src/bin/sh/jobs.c,v
 retrieving revision 1.69
 diff -u -r1.69 jobs.c
 --- jobs.c	5 Sep 2005 17:57:19 -0000	1.69
 +++ jobs.c	13 Dec 2005 18:38:26 -0000
 @@ -929,6 +929,8 @@
  		if (pid <= 0)
  			return -1;
  	}
 +	if (errno == ECHILD)
 +		job->state = 1;
  	if (pid <= 0)
  		return pid;
  	INTOFF;
 %%%
 
 Not sure they are correct, need to think about the issue a bit more :-)
 
 -- 
 Maxim Konovalov


More information about the freebsd-bugs mailing list