[comp.sys.hp] Strange signal/process group feature in HP-UX

tml@tik.vtt.fi (Tor Lillqvist) (02/06/91)

We have noticed an interesting feature related to signals and process
groups (and sessions) in HP-UX 7.0 (both s800 and s300).  Here is a
description of the scenario:

A process, let's call it "master", detaches itself from the
controlling terminal and wants to be sure it doesn't acquire a new
one:

fork(), setsid(), signal(SIGHUP, SIG_IGN), and fork() again.  The last
child is the one that continues executing.  Maybe this is overdoing it
a bit.

Now master starts several other processes.

Later you send a SIGSTOP to one of master's children, let's call it foo.
It stops as you would expect.

Then you send a SIGKILL to another of master's children.  Now comes
the interesting bit:  foo continues!

I even wrote a small demonstration program:

#ifdef __STDC__
#define _HPUX_SOURCE
#endif

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>

#define NCHILDREN 5

#define Sleep (void) sleep
#define Printf (void) printf

main(argc, argv)
     int argc;
     char **argv;
{
  int i, j;
  pid_t pid, child[NCHILDREN];
  long lrand48();
  void srand48();

  if (argc == 1) {
    pid = fork();
    if (pid == -1)
      perror("fork"), exit(1);
    else if (pid > 0)
      exit(0);
    
    if (setsid() == -1)
      perror("setsid"), exit(1);
    
    (void) signal(SIGHUP, SIG_IGN);

    pid = fork();
    if (pid == -1)
      perror("fork");
    else if (pid > 0)
      exit(0);

    Printf("now in grandchild...\n");
  }
  
  Sleep(2);

  (void) setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);

  Printf("starting children...\n");

  for (i = 0; i < NCHILDREN; i++) {
    child[i] = fork();
    if (child[i] == -1)
      perror("fork"), exit(1);
    else if (child[i] == 0) {
      pid = getpid();
      for (i = 0; i < 10; i++) {
	time_t t = time((time_t*) NULL);
	
	Printf("%d: %s", pid, ctime(&t));
	Sleep(5);
      }
      exit(0);
    }
  }

  Printf("children have started... sleeping again...\n");
    
  Sleep(3);
    
  srand48((long) time((time_t*) NULL));

  i = lrand48() % NCHILDREN;
  Printf("stopping child %d...\n", child[i]);
  if (kill(child[i], SIGSTOP) == -1)
    perror("kill"), exit(1);

  Sleep(13);

  while ((j = lrand48() % NCHILDREN) == i)
    ;
  Printf("killing child %d...\n", child[j]);
  if (kill(child[j], SIGKILL) == -1)
    perror("kill"), exit(1);

  Sleep(200);
  return(0);
}

When you run this program you notice that as soon as it says "killing
child %d" the previously stopped one continues...

I tried a similar program on VAX Ultrix 3.1 (using setpgrp and
TIOCNOTTY), and this behaviour didn't occur.
--
Tor Lillqvist,
working, but not speaking, for the Technical Research Centre of Finland