How to send child signal when parent exits?

Tony Olekshy tony at oha.UUCP
Sun Feb 25 07:27:16 AEST 1990


In message <1416 at yarra.oz.au>, bgg at yarra.oz.au (Benjamin G. Golding) writes:
>
> In article <8948 at wiley.UUCP> david at wiley.UUCP (David Hull) writes:
> > I've written a replacement for biff/comsat that works even when the
> > mail spool directory is mounted over NFS and the mail is being delivered
> > on another machine.  It wakes up every minute and stats the user's mail
> > file to decide whether he has received any new mail.
> >
> > The program should automatically die when the user logs out.
> 
> Why not reorganise the order of the programs?

Well, that's one way, or you could have the parent spawn both the shell
and mail watcher and kill the living when either dies, or fiddle something
with SIGHUP (I think), or have the child try to kill(parent_id, 0) once
around each loop.

However, the following will also work as long as the parent doesn't close
the writing end of the pipe until it is exiting.  You should clean it up
to check all return codes, of course.  Interested readers are referred to
the pipe, read, and exit man pages:

>From pipe:

     Description
         fildes[0] is opened for reading and fildes[1] is opened for writing
	 and the O_NDELAY flag is clear.  The descriptors remain open across
	 fork system calls...

>From read:

    When attempting to read from an empty pipe:

        If O_NDELAY is clear, the read will block until data is written to
	the file or the file is no longer open for writing.
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    read will fail if one or more of the following are true:

        A signal was caught during the read system call.  [EINTR]

>From exit:

    All of the file descriptors open in the calling process are closed.

----------------------------------------------------------------------------

#include <stdio.h>
#include <signal.h>
#include <errno.h>

#define CHILD_CYCLE 2	/* Delay between child ops. */

childWork()
{
    alarm(0);
    /* Put your mail watching code here. */
    fprintf(stderr, "Child working!\n");
    }

main()
{
    int		 pfd[2];
    int		 pid;
    char	 byte;

    if (pipe(pfd) == -1) perror("pipe");

    switch (pid = fork()) {

	case -1:
	    perror("fork");
	    exit (1);

	case 0:			/* Child */
	    close(pfd[1]);
	    signal(SIGINT, SIG_IGN);
	    fprintf(stderr, "Child %d running...\n", getpid());

	    while (1) {
		alarm(CHILD_CYCLE);
		signal(SIGALRM, childWork);
		errno = 0;
		read(pfd[0], &byte, 1);	/* Blocks till write or sig. */
		switch (errno) {
		    case 0:		/* Parent exit closed pipe. */
			fprintf(stderr, "Child %d done.\n", getpid());
			exit (0);
		    case EINTR:		/* Alarm rang through childWork. */
			break;
		    default:		/* Hmmm? */
			fprintf(stderr, "Child read errno %d.\n", errno);
			exit (1);
		    }
		}
	    /* NOTREACHED */

	default:		/* Parent */
	    break;
	}

    close(pfd[0]);
    fprintf(stderr, "Parent %d execing shell, ^D to stop...\n", getpid());
    execl("/bin/sh", "sh", NULL);
    perror("exec");
    exit (1);
    }

--
Yours, etc., Tony Olekshy (...!alberta!oha!tony or tony at oha.UUCP).



More information about the Comp.unix.wizards mailing list