cpipebusy-waiting

In C, can we read from pipes without busywaiting, may be using callbacks or other ways?


I was trying to read from the STDOUT of a forked process. However, if I am reading from the pipe in an infinite for loop, it would be busy waiting even if no data is coming through the pipe (please correct me if I am wrong), and I guess there must be a better way to do it other than using sleep if it is for short intervals, may be with callbacks, which I am not sure about. The below is the code snippet that I tried.

pid_t pid = fork();  
switch (pid) {
    case 0:
        dup2 (pipes[1], STDOUT_FILENO );
        dup2(pipes[1], STDERR_FILENO); 
        close(pipes[0]); 
        close(pipes[1]);
        execv(path, args);
        break;
    default :
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        child_pid = pid;
        signal(SIGHUP, mysighandle);
        close(pipes[1]); 
        ssize_t nbytes;
        for (;;) {
            nbytes = read(pipes[0], buf, BUFSIZE); 
            if (nbytes == -1){
                break;
            }
            if (nbytes == 0) {
                break;
            }
            syslog(LOG_NOTICE, "%s", buf);

Can someone please suggest a better way without busywaiting, that could be used to read data from pipes? Since I am a beginner in C, any references to code-snippets are appreciated.

Regards.


Solution

  • In your code, you haven't set your pipe to non-blocking mode (at least, I assume you haven't, since you don't actually show how you're opening it), and so read() is doing a blocking read. That is, if there is no data available, but some process still has the pipe open for writing, then it will automatically pause your process until more data is available (and will then read that data into the buffer).

    Thus, your code works just fine as it is, and there's no need to change it.

    (That is, unless you want to read from multiple pipes at the same time, or wait for data while also doing something else in the same thread, in which case you should indeed use select() and (possibly) non-blocking I/O.)