[comp.unix.programmer] Is this a possible bug in SunOS setpgrp

wkt@csadfa.cs.adfa.oz.au (Warren Toomey) (05/21/91)

I include a short program which appears to demonstrate a bug in the
setpgrp() under SunOS 4.1.1. The program works under Pyramid OSx, and
I think should work under previous version of SunOS. If anybody can show
me that the bug is in fact a programming error I'd be most happy!

Thanks in advance,

	Warren Toomey.


---- cut here, and unshar ----
echo x - fred.c
sed '/^X/s///' > fred.c << '/'
X#include <signal.h>
X#include <sgtty.h>
X#include <termio.h>     /* Need this for TCGETA definition */
X
X
X/* The following program exhibits a possible bug in SunOS 4.1.1. Compile
X * this program as fred: cc -o fred fred.c and run it with no arguments.
X *
X * The program sets the terminal to stop background writes to the terminal,
X * and forks a child. The child moves itself to a new process group, and
X * tries to write to the terminal in one of two ways: just after the fork(),
X * and after the exec().
X *
X * The parent waits for the SIGCHLD caused by the write, and attempts to
X * bring the child back into the parent's pgrp, thus allowing the write to
X * succeed.
X *
X * However, this fails under SunOS 4.1.1 when the child only tries to write
X * AFTER the exec(). See `THE BUG' comment below.
X */
X
Xvoid catchsig()
X { }
X
Xvoid dowrite()
X { write(1,"Writing to stdout\n",18); exit(0); }
X
X
Xmain(argc,argv)
X int argc;
X char *argv[];
X {
X  struct termio tbuf;
X  int i;
X
X  if (argc>1) dowrite();	/* If we are called with >1 args, write */
X
X/* Set up the terminal so that SIGTTOUs are sent to
X * processes which are not members of the owning process group
X */
X  if (ioctl(0,TCGETA,&tbuf)) perror("ioctl in settou");
X  tbuf.c_lflag |= TOSTOP;
X  if (ioctl(0,TCSETA,&tbuf)) perror("ioctl s");
X
X
X/* Catch the SIGCHLD with a null handler.
X */
X  signal(SIGCHLD,catchsig);
X
X/* Fork, and make the child write on stdout.
X */
X  switch(i=fork())
X   {
X    case -1: printf("Could not fork\n"); exit(1);
X
X    case 0 :			/* The child */
X
X	     i=setpgrp(0,getpid());	/* Take us out of the pgrp */
X	     sleep(2);			/* Wait for a bit */
X
X/* THE BUG: 
X *
X * If you uncomment the printf line, the program works everywhere.
X * But if you leave the line commented, the program dies with an
X * EPERM error in the parent's setpgrp() under SunOS Release 4.1.1.
X * It works under Pyramid OSx, generic 4.3BSD system.
X */
X	     /* printf("Can I write??\n"); */
X	     execlp("fred","arg1","arg2",0);
X	     exit(0);
X
X    default:			/* The parent */
X
X	     printf("Forked, now we pause()\n");
X	     pause();			/* Wait for SIGCHLD */
X	     if (setpgrp(i,getpgrp(0))==-1)  /* set pgrp to the parents's */
X   		{ perror("Setpgrp failed"); exit(1); }
X	     kill(i,SIGCONT);		/* Start the child up */
X	     sleep(1);			/* and finish */
X	     exit(0);
X   }
X }
/

urban@cbnewsl.att.com (john.urban) (05/22/91)

In article <1991May21.022214.1189@sserve.cc.adfa.oz.au> wkt@csadfa.cs.adfa.oz.au (Warren Toomey) writes:
>I include a short program which appears to demonstrate a bug in the
>setpgrp() under SunOS 4.1.1. The program works under Pyramid OSx, and
>I think should work under previous version of SunOS. If anybody can show
>me that the bug is in fact a programming error I'd be most happy!
>
>Thanks in advance,

When fred is compiled on AT&T UNIX System V/x86 Release 4.0 Version 2.1, I get:

$ ./fred
Forked, now we pause()
Writing to stdout
$

If I then change fred and uncomment the 'bug' line I get:
$ ./fred
Forked, now we pause()
Can I write??
Writing to stdout
$

Sincerely,

John Ben Urban

decot@hpcupt1.cup.hp.com (Dave Decot) (06/04/91)

Caution: BSD-derived systems such as SunOS and System V-derived systems (such
as SunOS /-:) have different semantics for the function setpgrp().

In fact, the BSD version has two arguments, whereas the System V version
has no arguments.

Check your documentation carefully.  On POSIX systems, use setpgid()
or setsid() as appropriate to your situation.

Dave