If I fork() and then do an execv(), who owns the c

2019-04-14 23:27发布

问题:

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?

回答1:

Both processes have their stdin connected to the terminal (or whatever the original process's stdin was connected to). This doesn't change when you call execv. If both processes try to read from stdin 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 calling execv to put it in its own session and remove its controlling terminal.



回答2:

fork() calls dup() on every single file descriptor. In effect you get a copy of all the files in the child. Some "processes" (via hooks) may detect the fork() 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 on execv(). 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.

freopen("/dev/null", "r", stdin);

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):

for(;;) sleep(0x7FFFFFFF); // for(;;) is probably superfluous

That's probably the simplest way, there are many others such as using select() on a file you know will never change...



回答3:

I think it APPEARS as though my_other_app has priority since the other child process has sleep(3).