[BUG][PATCH] lash,hush setting childs pgrp

Bernhard Fischer rep.nop at aon.at
Sun Jun 11 10:46:28 UTC 2006


Hi,

In lash, if i repeatedly do
$ touch a
i get
lash: tcsetpgrp: Operation not permitted

Likewise in hush:
$ while touch a;do touch a;done
hush: tcsetpgrp-3: Invalid argument
Also hush sometimes just hangs for this command.

This behaviour was reported by Jayush Luniya here:
http://www.busybox.net/lists/busybox/2004-May/011574.html
"
I am using the busybox-0.60.5 with uClinux on a processor without an MMU
with the following configuration option enabled.

#define BB_FEATURE_SH_STANDALONE_SHELL
#define BB_FEATURE_SH_APPLETS_ALWAYS_WIN
Also vfork() is used instead of fork() as there is no MMU unit.
However whenever I run a command on the shell the following error
message
is displayed:

 # ls
lost+found  dev         tmp         sbin        bin
ls: tcsetpgrp: Operation not permitted

This happens due to the following call in function insert_job() in
lash.c
tcsetpgrp() here returns -1 and sets errno = EPERM.

if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
              perror_msg("tcsetpgrp");
On further going thru the source code of busybox and the kernel source I
could figure out what the problem is.

The tcsetpgrp() here is setting shell's pgrp to that of the first
process
of the new job group. But by that time the child process has terminated
and hence it sets errno to EPERM ( -1 ) .  The child process terminates
before the parent bcoz I am using vfork() instead of fork() and due to
BB_FEATURE_SH_STANDALONE_SHELL && BB_FEATURE_SH_APPLETS_ALWAYS_WIN
option
the execve() function is not called by the child and hence the parent
does
not get scheduled unless the child terminates.

So do I need to have tcsetpgrp() at this case? I think the problem can
be
solved by calling waitpid() and if it does not return with errno =
ECHILD
( ie Child hasnt terminated yet ) then only calling  tcsetpgrp().

if( (waitpid((newjob->pgrp), &status , WNOHANG) >= 0) && errno !=ECHILD)
{
     if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
              perror_msg("tcsetpgrp");
}

It works properly with this. I would like to know whether this is
correct
solution. A similar prolem also exists in hash.c
"

AFAICT his proposed solution works and i intend to apply the attached
patch for lash to repair this bug. The downside is that it adds
26B, so perhaps there is an alternative approach to the attached
sledgehammer..

Comments?
TIA,
Bernhard

   text	   data	    bss	    dec	    hex	filename
   7440	    196	     60	   7696	   1e10	shell/lash.o.orig
   7466	    196	     60	   7722	   1e2a	shell/lash.o


-------------- next part --------------
Index: shell/lash.c
===================================================================
--- shell/lash.c	(revision 15351)
+++ shell/lash.c	(working copy)
@@ -1319,10 +1319,16 @@
 	} else {
 		newjob->job_list->fg = thejob;
 
-		/* move the new process group into the foreground */
-		/* suppress messages when run from /linuxrc mag at sysgo.de */
-		if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
-			bb_perror_msg("tcsetpgrp");
+		/* see if the new process is still running at all. It may have already
+		   completed successfully by now, so we'd get -EPERM when trying to poke
+		   at it */
+		if ((waitpid((newjob->pgrp), NULL , WNOHANG) >= 0) && errno != ECHILD) {
+			/* move the new process group into the foreground */
+			/* suppress messages when run from /linuxrc mag at sysgo.de */
+			if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY) {
+				bb_perror_msg("tcsetpgrp");
+			}
+		}
 	}
 #endif
 }


More information about the busybox mailing list