PDA

View Full Version : execution in background


mile1982
10-12-2004, 01:16 PM
hey

im having trouble understanding how to execute commands in the background. i did some research and saw that you only have to fork and not wait for the child to finish. in another case you have to change the process group. i ve really tried both of them but i just cant get them to work. so i anyone feels like helping out, id appreciate it a lot. thanks

heres what i got so far.

a->background is set to 1 if one of the arguments on the command line equals '&'.



/* create a process space */

if ((pid = fork()) < 0) {

perror ("Fork failed");
exit(errno);
}

if (!pid) { // pid == 0

printf(" \n if (!pid) = %d ", pid);

printf (" child process[%d]\n", getpid ()); /* Display child PID */
/* Child process */

if (a->background == 1) {

// so when it comes across a '&',

if (fork () == 0) {

// just fork(); do not wait for the child
signal (SIGQUIT, originalQuitHandler); /* Oldhandler */
setpgid (0, getpid ()); /* Change process group */
execvp(a->com_name, a->argv);
}
}

else {

/* This is the child, so execute the ls */
execvp (a->com_name, a->argv);
}
}

if (pid) {

printf(" \n if (pid) = %d ", pid);

/* We're in the parent; let's wait for the child to finish */
waitpid (pid, NULL, 0);
}

return;



thanks again

mile 1982 8O

RobSeace
10-12-2004, 09:48 PM
In the second fork(), you want to have the parent of that (the child
of the first fork()) immediately _exit()... That will let the original
parent immediately detect the death of the child, and orphan the
grand-child process to be inherited by init...

i3839
10-12-2004, 10:45 PM
The thing is that executing something in the background isn't the same as detaching a child, that can be done easily with setsid(). All you want to do is redirecting the stdin of the child to something else than the stdin of your parent, so that your parent can handle new commands. At least that seems to be the case with Bash. When executing something with & at the end it still spit its stuff in the console, so stdout isn't redirected, and if the child exits then bash returns the return value of that process, so it wasn't detached.

RobSeace
10-13-2004, 01:14 PM
True, if you ever want to get at the return value of that background
task, then you certainly don't want to orphan it via the double-fork()
trick like that... Just do a normal single fork(), and simply don't
wait() on it in the parent; instead, setup a SIGCHLD handler to be
notified when the child finally dies, and wait() on it then... But, given
that you were already double-fork()'ing, I assumed you didn't care
about the background task's exit value, anyway...

Oh, and I'm not sure what you mean about redirecting stdin, i3839...
No shell that I know of (including bash) will auto-redirect your stdin
(or stdout/stderr) when you simply background a task... You have
to "nohup" it, or something similar, to cause that to happen... But,
if you run a background task that tries to read from stdin, you'll find
both it and the parent shell fighting for tty input...

i3839
10-13-2004, 05:21 PM
It seems that if you run a program with & at the end in at least bash, then it won't get any data from the terminal on which bash is, all data goes to bash. So either bash wins the fight always, or the stdin of the child process was redirected to something else than bash's old stdin.

nohup is to redirect stdout and stderr, and to ignore signals like SIGHUP which programs normally don't ignore. It doesn't redirect stdin like bash does for a background process.

RobSeace
10-13-2004, 10:11 PM
It doesn't redirect stdin like bash does for a background process.


No, really, I'm telling you, bash does NOT redirect stdin for
background tasks...


[agrajag]$ tty
/dev/pts/3
[agrajag]$ ls -l /proc/self/fd &
[1] 21359
total 0
lrwx------ 1 ras program 64 Oct 13 16:11 0 -> /dev/pts/3
lrwx------ 1 ras program 64 Oct 13 16:11 1 -> /dev/pts/3
lrwx------ 1 ras program 64 Oct 13 16:11 2 -> /dev/pts/3
lr-x------ 1 ras program 64 Oct 13 16:11 3 -> /proc/21359/fd/
[agrajag]$
[1]+ Done ls --color=auto -F -l /proc/self/fd
[agrajag]$


As you can see, stdin is still the tty...

However, you do seem to be right about the background task
losing the fight for tty input... It looks like as soon as the BG task
attempts to read from its stdin, it gets hit with SIGTTIN, which
locks it up... This happens because bash puts the the process
in a separate pgrp, which isn't the main pgrp for the tty, and Linux's
tty layer kernel code then detects this condition (reading on a tty
from a process not in the tty's pgrp) and stops it with SIGTTIN...
Nifty... But, I've definitely used systems where such stuff just
wasn't done, and you could background an interactive task,
which would then split the tty input with the shell... (Which is
usually highly annoying when it happens, and almost never what
you want to happen... ;-) So, the Linux method is definitely the
more correct and desirable behavior, I'd say...)

But, in any case, the stdin of the BG task remains the same,
anyway... (And, an appropriately annoying BG task could also
conceivably foreground itself by manipulating its pgrp, and still
cause the input splitting havoc previously mentioned... ;-))

i3839
10-14-2004, 12:01 AM
Yes, you're right, it seems. :-) Though this means ugly terminal stuff is going on, I'd forgot about that. Sessions, process groups, controlling terminals; no idea what's Linux specific and what not, nor how it all works together, but it's a bit more clear now.

To mile1982:

Read the manpages: setpgid(2), tcsetpgrp(3), setsid(2), termios(3).