Date: Tue, 13 Dec 2005 19:00:17 GMT From: Maxim Konovalov <maxim@macomnet.ru> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/90334: /bin/sh trap problem Message-ID: <200512131900.jBDJ0HCF097638@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/90334; it has been noted by GNATS. From: Maxim Konovalov <maxim@macomnet.ru> To: Dmitriy Kirhlarov <dkirhlarov@oilspace.com> Cc: bug-followup@freebsd.org, kst@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200512131900.jBDJ0HCF097638>