root@oid.UUCP (Admin-P.L. Aeten) (10/11/89)
Having to write a file transmission program which was to be launched after some tape processing was done I was confronted with what I consider to be abnormal behaviour of 'setpgrp'. Since the tying up of a terminal (operators terminal using menu interface) was unacceptable (yes background (&) was possible but the need to know was overwhelming...well read on. It seems the "setpgrp" call behaves as designed and as per documentaion. However if followed by a 'while' or 'for' (finite or infinite) loop it will not detach a process from the controlling tty. I've tried both. Following are two somewhat degenerate code fragments. char *progname; main(argc, argv) char *argv; int argc; { . . . if( setpgrp() == FAIL ) { perror("Detach failed: ", progname); exit(2); } for( cnt = 0; cnt < 2; cnt++) { do something } . . exit(some val); } The above will tie up the terminal invoked from as does the following: char *progname; main(argc, argv) char *argv; int argc; { . . . if( setpgrp() == FAIL ) { perror("Detach failed: ", progname); exit(2); } while(somecondition) { do something } . . exit(some val); } In order to free up the terminal on the 'setpgrp' I had to arrange the demise of the parent prior to the call. . . . . . if( pid = fork()) { if( pid == -1) { perror("Can't fork process: ", progname); exit(2); } exit(0); } umask(022); setpgrp(); . . . [Additional information: I closed all filedes associated with the terminal but to no avail... SysVR2.1.2 with V3.1 compiler exhibits the same condition] I am at a complete loss to explain this. Being a curious sort I can't let this one get by. Can anyone shed some light on why this occurs? Is the compiler (AT&T CPLU 4.2) at fault or is this not a defect? Or am I doing something wrong? Thank you all! Peter P. L. Aeten Manager - UNIX Production Systems VU/TEXT Information Services {attmail,dsinc,netsys,lll-winken}oid!paeten Bus [215-574-4477] or Home [215-461-5540]
cpcahil@virtech.UUCP (Conor P. Cahill) (10/13/89)
In article <1970@oid.UUCP>, root@oid.UUCP (Admin-P.L. Aeten) writes: > Having to write a file transmission program which was to be launched after some > tape processing was done I was confronted with what I consider to be abnormal > behaviour of 'setpgrp'. Since the tying up of a terminal (operators terminal > using menu interface) was unacceptable (yes background (&) was possible but > the need to know was overwhelming...well read on. > It seems the "setpgrp" call behaves as designed and as per documentaion. However > if followed by a 'while' or 'for' (finite or infinite) loop it will not detach > a process from the controlling tty. I've tried both. It *appears* from your post that you interpret "detach a process from the controlling tty" as letting the program continue running while you have control of the tty to perform other operations. The setpgrp() program only places the current program into a different process group and disconnects the link from the process to the controlling tty. Disconnecting the link from the controlling tty means that signals (like SIGHUP) generated in the tty driver will not be delivered to this process and open(/dev/tty) will fail, since this program is no longer connected to a tty. However, what you want to do is place your program in the background. Yes, you can do that from the command line (as you noted with the &) or you can have the program do it itself (as you final example does). This is the only mechanism available under UNIX to do what you want to do. This is true for all UNIXs (that I have seen). PS-> you should still do a setpgrp() after the fork to ensure that your new program does not recieve signals from the terminal. -- +-----------------------------------------------------------------------+ | Conor P. Cahill uunet!virtech!cpcahil 703-430-9247 ! | Virtual Technologies Inc., P. O. Box 876, Sterling, VA 22170 | +-----------------------------------------------------------------------+
konczal@mail-gw.ncsl.nist.gov (Joe Konczal) (10/14/89)
> It seems the "setpgrp" call behaves as designed and as per > documentaion. However if followed by a 'while' or 'for' (finite or > infinite) loop it will not detach a process from the controlling > tty. I've tried both... I looked at the source for a BSD 4.3 daemon to see how it detaches from the controlling terminal and came up with this code fragment which works in SunOS 4.0. Is there anything similar to this in System V? int fd; if ((fd = open("/dev/tty", 2)) < 0) /* detach process from terminal */ error("open /dev/tty"); else { if (ioctl(fd, (int) TIOCNOTTY, (char *) 0) < 0) error("ioctl TIOCNOTTY"); close(fd); } setpgrp(0, 0); Joe Konczal
chip@ateng.com (Chip Salzenberg) (10/14/89)
According to cpcahil@virtech.UUCP (Conor P. Cahill): >The setpgrp() program only places the current program into a different >process group and disconnects the link from the process to the controlling >tty. Quite. >PS-> you should still do a setpgrp() after the fork to ensure that your >new program does not recieve signals from the terminal. You should also do another fork() AFTER the setpgrp(). Otherwise, the child process remains a process group leader. And if a process group leader without a controlling tty opens a tty that no other process has open at the time [inhale], then that tty becomes the process's controlling tty. So the child must fork() again; then the grandchild process is a safe daemon. Finally: /* * Daemon code. * Insert error checking to taste. */ if (fork() != 0) exit(0); setpgrp(); if (fork() != 0) exit(0); /* * And away we go... */ Personally, I think this whole "setpgrp does two jobs" is a grody hack. It's as bad as the "setuid(getuid()) is reversible for all setuid programs except setuid-root programs" grody hack. Well, maybe not that bad. -- You may redistribute this article only to those who may freely do likewise. Chip Salzenberg at A T Engineering; <chip@ateng.com> or <uunet!ateng!chip> "'Why do we post to Usenet?' Naturally, the answer is, 'To get a response.'" -- Brad "Flame Me" Templeton
karish@forel.stanford.edu (Chuck Karish) (10/15/89)
In article <253664A4.20995@ateng.com> chip@ateng.com (Chip Salzenberg) wrote: >Personally, I think this whole "setpgrp does two jobs" is a grody hack. How about setsid()? It does three jobs: setpgrp()'s two, plus making the caller the foreground process. Chuck Karish karish@mindcraft.com (415) 493-9000 karish@forel.stanford.edu
kremer@cs.odu.edu (Lloyd Kremer) (10/16/89)
In article <253664A4.20995@ateng.com> chip@ateng.com (Chip Salzenberg) writes: >You should also do another fork() AFTER the setpgrp(). Otherwise, the child >process remains a process group leader. And if a process group leader >without a controlling tty opens a tty that no other process has open at the >time [inhale], then that tty becomes the process's controlling tty. So the >child must fork() again; then the grandchild process is a safe daemon. > >Finally: > > /* > * Daemon code. > * Insert error checking to taste. > */ > > if (fork() != 0) > exit(0); > setpgrp(); > if (fork() != 0) > exit(0); > > /* > * And away we go... > */ Do you need two forks? Wouldn't the "second" fork alone be sufficient? Example: setpgrp(); /* original parent divorces controlling tty and becomes process group leader */ close(0); close(1); close(2); /* sure, why not? */ if(fork() != 0) exit(0); /* death of parent backgrounds the process */ /* child process will be non-process-group-leader */ /* And away we go... */ -- Lloyd Kremer ...!uunet!xanth!kremer Have terminal...will hack!