I am writing a Linux application. What happens if I call fork()
and then run an application that takes console input? Consider the code below:
int process_id = fork();
if (process_id != 0) {
/* this is the parent process */
error = execv("../my_other_app", "parameter1", NULL);
if (error < 0) {
printf("error!");
}
} else {
/* this is the child process. Wait for my_other_app to set up */
sleep(3);
/* now continue */
}
printf("########## press ENTER to stop ##########\n");
getchar();
exit(0);
The thing is, my_other_app
also has a press ENTER to stop message. So when I do the getchar()
call, which application is reading it? The main application or the my_other_app
that I launched with execv
?
EDIT: It appears through testing that my_other_app
takes priority over the console. Does this happen every time? Is there a way to make sure the console is instead owned by the main process?
fork()
callsdup()
on every single file descriptor. In effect you get a copy of all the files in the child. Some "processes" (via hooks) may detect thefork()
and close some file descriptors, but that's very unlikely. Some files may be opened with a specific flag saying that it should be closed onexecv()
. stdin is not one of them.You have two solutions, just close stdin in the child process, but that can cause problems, or replace it with
/dev/null
.You can do the same for stdout and stderr.
Adding a 'wait forever' at the end of the program (since you cannot do getchar() anymore):
That's probably the simplest way, there are many others such as using select() on a file you know will never change...
I think it APPEARS as though
my_other_app
has priority since the other child process hassleep(3)
.Both processes have their
stdin
connected to the terminal (or whatever the original process'sstdin
was connected to). This doesn't change when you callexecv
. If both processes try to read fromstdin
at the same time, it's unpredictable which one will get the input.If you want to disconnect the child process from the terminal, you should call
setsid()
before callingexecv
to put it in its own session and remove its controlling terminal.