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 | +-----------------------------------------------------------------------+
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!
chip@ateng.com (Chip Salzenberg) (10/18/89)
According to kremer@cs.odu.edu (Lloyd Kremer): >According to chip@ateng.com (Chip Salzenberg): >>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. > >Do you need two forks? Wouldn't the "second" fork alone be sufficient? Unfortunately, the first fork() is required to ensure that setpgrp() will work correctly. You see, setpgrp() has two functions: 1. Make the process a process group leader. 2. Make the process have no controlling tty. Here's the ugly part: If function #1 isn't needed -- i.e. if the process is already a process group leader -- then function #2 is _not_ performed. In other words, if a process is a process group leader, setpgrp() does nothing. (Sigh.) So summarize: The fork() _before_ the setpgrp() guarantees that the child isn't a process group leader, and thus ensures that setpgrp() will work, losing the controlling tty. The fork() _after_ the setpgrp() guarantees that the grandchild won't ever get a controlling tty by accident. Now you see why I said that setpgrp() is a grody hack. :-( -- 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