From: lpc@dickens.com (Luis P Caamano)
Subject: Re: system() and SIGCHLD
Date: Fri, 21 Aug 1992 13:54:07 GMT
Organization: Dickens Data Systems, Inc.

In article <94029@bu.edu> tasos@cs.bu.edu (Anastasios Kotsikonas) writes:
>A few weeks ago I posted the following question to comp.unix.programmer:
>
>If process A forks B, then A does a system(), is A supposed to receive
>a SIGCLD when system() returns?
>

I ran your program.  I got the bug on both AIX 3.1.5 and 3.2. However, 
on an old 9021 AIX (3.1.0) it ran fine by changing the system line
to
    system ("sleep 4"); 

Anyway, I added a mysystem() function to your program.  mysystem()
is doing what I think (I might be wrong ...) system() should do.

The man page for the system subroutine says that it checks for a
trusted shell.  I don't know how to check from which shell I'm running
other than traverse up the process tree (which is kind of expensive).
I suspect that a simple way to find out if you're running under a trusted 
shell might be part of the misterious priv.h functions (setpriv, getpriv, 
privilege, privcheck, etc.)  Whatever, I added some pseudo code
for that part since I don't think you're running the trusted shell.

>
>If any can suggest a workaround I would really appreciate it.
>

I don't know what you are doing with SIGCLHD, but you can always check
the pid of the reaped child.

Another workaround is mysystem().

Here is systes1.c

----CUT HERE-----8<------systest1.c----------8<--------------


#include <stdio.h>
#include <signal.h>
#include <sys/types.h>


int pid;

main ()
{
  extern int sighandle();

#ifdef SIGCLD
  signal (SIGCLD, (void *) sighandle);
#else
  signal (SIGCHLD, (void *) sighandle);
#endif
  if ((pid = fork ()) < 0)
    perror ("Cannot fork"),
    exit (1);
  else if (pid == 0)
    while (1);
  else
    mysystem ("/bin/echo > /dev/null"); /**/
  sleep (2);
  printf ("system() OK.\n");
#ifdef SIGCLD
  signal (SIGCLD, SIG_DFL);
#else
  signal (SIGCHLD, SIG_DFL);
#endif
  kill (pid, SIGKILL);
  exit (0);
}

sighandle (sig)
int sig;
{
  fprintf (stderr, "system() bug.\n");
#ifdef SIGCLD
  signal (SIGCLD, SIG_DFL);
#else
  signal (SIGCHLD, SIG_DFL);
#endif
  kill (pid, SIGKILL);
  exit (2);
}

mysystem(char *cmd)
{
int	status, rc;
pid_t	pid;
struct sigaction sa, oldi, oldq, oldc;

	printf("mysystem() function\n");

	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0 ;

	sa.sa_handler = SIG_DFL;
	sigaction(SIGCHLD,&sa, &oldc);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGINT,&sa, &oldi);
	sigaction(SIGQUIT,&sa, &oldq);

	if((pid = fork()) == 0) {
#ifdef KNOWABOUTTSH
	    if (someway_to_find_if_it_is_a_trusted_shell) {
		(void) execl("/bin/tsh", "tsh", "-c", cmd, 0);
		_exit(-1);
	    }
#endif
	    (void) execl("/bin/bsh", "bsh", "-c", cmd, 0);
	    _exit(-1);
	}


	while((rc = waitpid(pid, &status, 0)) != pid && rc != -1)
		;

	sigaction(SIGCHLD,&oldc,NULL);
	sigaction(SIGINT,&oldi,NULL);
	sigaction(SIGQUIT,&oldq,NULL);

	return(rc == -1 ? rc : status);
}
----CUT HERE-----8<------systest1.c----------8<--------------
-- 
---------------------------------------------------------------------------
Luis P. Caamano                    |         lpc@dickens.com
Dickens Data Systems, Inc.         |         uunet!dickens.com!lpc
Atlanta, GA                        |         (404) 475-8860
---------------------------------------------------------------------------
If I think I know it all, I'll stop learning. -myself
The more I learn, the more I know I know nothing. -somebody else