[net.lang.c] putting C programs in the background

lvc@cbscc.UUCP (Larry Cipriani) (01/15/85)

To put a C program in the background (not from the shell)
try the following:

	if (fork() != 0) exit(0);

Simple yes.  Obvious, well maybe.  And don't forget to
setup those signal handlers and file descriptor just right.

			Larry Cipriani
			cbscc!cbsch!lvc

mr@hou2h.UUCP (M.RINDSBERG) (01/15/85)

Can a program put itself into the background ???
(SYS V R2)

							Mark

mr@hou2h.UUCP (M.RINDSBERG) (01/15/85)

This is a continuation of the last article(Sorry).

Can a program put another program into the background given its
pid.     |
         +-----> Not a supervisory or parent .

						Mark

ron@brl-tgr.ARPA (Ron Natalie <ron>) (01/18/85)

> This is a continuation of the last article(Sorry).
> 
> Can a program put another program into the background given its
> pid.     |
>          +-----> Not a supervisory or parent .
> 
> 						Mark

In the genereal case no. The problem that people here have a hard
time coping with is that "BACKGROUND" is not a characturistic of
a UNIX process.  BACKGROUND happens when your shell decides not to
wait for a process to finish.  There is nothing you can do to the
process itself to make this happen, what you have to do is do something
to the parent to make it stop waiting.

In 4.2 they handle this by putting special code in the shell.  Sending
a certain signal to a process causes it to enter a special "STOP" state
and the parent gets an answer to it's wait call (similar to the way PTRACE
operates).  The parent can then CONTINUE the process without waiting for
it to finish, i.e. putting it in the background.  It can also CONTINUE it
and wait, i.e. leave it in the forground.  If you are clever in what you
do with file descriptors and process groups you can even move background
processes to the foreground.

Detesting the CSH, I now have a 5R2 bourne shell running on 4.2 BSD that
supports the above feature.

-Ron

guy@rlgvax.UUCP (Guy Harris) (01/18/85)

> Can a program put itself into the background ???
> (SYS V R2)
> 
> 							Mark

1) This is a discussion of features of UNIX, not C; it belongs in net.unix/
INFO-UNIX, and I've moved it there - all followups should go there only.

2) "background" is an ill-defined term in UNIX.  If your definition of
a background process is one that the shell isn't waiting for, then the
sequence posted in the original article will do it quite nicely; several
daemons in 4.2BSD do exactly that when invoked, so that you can fire up
a new version of the daemon without getting screwed if you forget to put
an "&" after it.

If your definition of a background process is one that the shell isn't
waiting for *and* which isn't reading from or writing to a terminal, again
possible in any version of UNIX - just close all the file descriptors
referring to terminals, and possibly reopen them to refer to something else
(again, the aforementioned daemons do this).

If your definition of a background process is one that meets all the above
conditions and which is ignoring signals like SIGINT and SIGHUP, again
doable - just do a "signal" call to ignore them.

If your definition of a background process is one that meets the above
conditions and which isn't attached to a terminal, it's doable in 4.2BSD
by trying to open "/dev/tty" and, if it succeeds, doing a TIOCNOPGRP "ioctl"
on the resulting file descriptor and then closing the descriptor, and in
System III/System V Release * by doing a "setpgrp" system call.  (The
aforementioned daemons do the former.)

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

guy@rlgvax.UUCP (Guy Harris) (01/18/85)

> Can a program put another program into the background given its
> pid.     |
>          +-----> Not a supervisory or parent .

No.

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

keesan@bbncca.ARPA (Morris M. Keesan) (01/18/85)

-----------------------------
>To put a C program in the background (not from the shell)
>try the following:
>
>	 if (fork() != 0) exit(0);
>
>Simple yes.  Obvious, well maybe.  And don't forget to
>setup those signal handlers and file descriptor just right.
>
>			 Larry Cipriani
>			 cbscc!cbsch!lvc

Almost.  Actually, a little too simple.
Better:

	pid = fork();
	if( pid < 0 )
	{
	    /* Print error message */
	    exit(1);
	}
	else if( pid > 0 )
	{
	    /* parent */
	    exit(0);
	}
	/* else pid == 0, this is the child.  Continue */

The correct thing to do about signals, to match what the shell does when it
puts something in background, is to ignore SIGINT and SIGQUIT.
-- 
			    Morris M. Keesan
			    {decvax,linus,ihnp4,wivax,wjh12,ima}!bbncca!keesan
			    keesan @ BBN-UNIX.ARPA

kendall@talcott.UUCP (Sam Kendall) (01/20/85)

> >To put a C program in the background . . . .
> 
> Almost.  Actually, a little too simple.  Better:
> 
> 	pid = fork();
> 	if( pid < 0 )
> 	{
> 	    /* Print error message */
> 	    exit(1);
> 	}
> 	else if( pid > 0 )
> 	{
> 	    /* parent */
> 	    exit(0);
> 	}
> 	/* else pid == 0, this is the child.  Continue */

Those "exit" calls should be "_exit", to avoid duplication of
buffered output.

	Sam Kendall	  {allegra,ihnp4,ima,amd}!wjh12!kendall
	Delft Consulting Corp.	    decvax!genrad!wjh12!kendall

dave@lsuc.UUCP (David Sherman) (01/25/85)

||	pid = fork();
||	if( pid < 0 )
||	{
||	    /* Print error message */
||	    exit(1);
||	}
||	else if( pid > 0 )
||	{
||	    /* parent */
||	    exit(0);
||	}
||	/* else pid == 0, this is the child.  Continue */

It's all stylistics, but my personal preference, particularly if the
parent is going to wait around, is

	switch(fork())
	{
	case -1;
		/* error message, maybe try again later */
		break;
	case 0:	/* child */
		/* exec or whatever */
	default:	/* parent */
		/* do things, then wait() */
	}

Of course, if done properly and not for some quick hack, that would
be switch(pid=fork()), and so on.

Dave Sherman
-- 
{utzoo pesnta nrcaero utcs}!lsuc!dave
{allegra decvax ihnp4 linus}!utcsrgv!lsuc!dave