简体   繁体   中英

C IPC waiting for child

So I have a program which creates a child process and executes a command (for example, ls). The parent will then use pipes to send to and get from the child. This works fine when I'm inputting commands myself from the command line.

However, when the input comes from a file, it seems like the child doesn't have enough time to run and I get NULL when reading from the pipe - even though there will be information coming from it.

Short of using sleep(), is there a better way to make sure the child has run before trying to read from it?

Thanks a lot!

If your haven't set your pipe file descriptor as non-blocking, then there should be no problem. Any read on the pipe will block until the child produces output; if you need to be responsive to multiple file descriptors (for example, standard input from the user and the pipe from the child process), use select() or poll() .

I assume it is fgets() that is returning NULL. That indicates either end-of-file (meaning that the child has closed its end of the pipe), or an error. You can check which of these is true using feof() or ferror() . Use perror() in the error case to see what the error actually is.

The question is how much control do you have on the child? If you are writing the child yourself then you can get the child to set a flag in shared memory that it has started (or touch a file or whatever tickles your fancy) and then only once you know the child is online run it.

If you don't have control over the child, there is still away to implement the above solution by wrapping the child with your own script which first launches the child then sets the shared memory, This could be in the form of a shell script as follows

#!/bin/sh

$CHILD
my_app_that_set_the_flag

Finally another alternative is to continue waiting aslong as you get NULL from the pipe, obviously this would lead to an infinite loop though if you can not garuntee that you will always get something on the pipe

Your parent thread needs to wait until the child is ready before it tries to read from the pipe. There are a couple of ways to do this.

First, you can use a condition variable. Declare a variable that both threads can access and set it to 0 . Your child thread will set it to 1 when is is ready for the parent to read. The parent will wait until the variable changes to 1 (using something like while(!condvar) sleep(1); ), then it will read from the pipe and reset the variable to 0 so that the child knows that the parent is finished.

Another option is to use a form of inter-process communication, such as signals . Similar to the condition variable method, the child thread will perform its work and then send a signal to the parent thread when it is done. The parent thread will wait until it receives the signal before it reads from the pipe, and then it can send a signal back to the child indicating that it is done.

Edit: Since you're spawning the child process with fork instead of with threads, you can't use a condition variable here (parent and child will have separate copies of it).

Instead, you can use the signal() and kill() functions to send signals between the processes. Before forking, use getpid to store a copy of the parent's pid (for the child process). Also store the return value of fork , since it will contain the child's pid.

To send a signal to the other process, use something like:

kill(parent_pid, SIGUSR1);

The receiving process needs to set up a signal handler. For example:

int signal_received = 0;
void signal_handler(int signal_num) {
    if (signal_num == SIGUSR1)
        signal_received = 1;
}

signal(SIGUSR1, signal_handler);

The function signal_handler now will be automatically called whenever the process receives signal number SIGUSR1 . Your thread would wait in a loop, watching for this variable to change using something like:

while (1) { // Signal processing loop
    // Wait here for a signal to come in
    while (!signal_received) { sleep(1); }

    // Wake up and do something
    read_from_pipe();
    ...
    signal_received = 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM