Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to flush I/O buffer in coprocess's pipe

Tags:

c

unix

flush

pipe

I am using pipe to write a coprocess. The parent creates two pipes, one pipe for write to the child and the other for read from child. But when I run the program, it is pending because it sets the printf to fully buffered as default. And I don't want to fflush the buffer in the child process source code.

I know the Chapter 19 in Advanced Programming in the UNIX Environment introduced a way using pseudo-terminal. But I want to know if there is a more sample way to do it. Thanks to all.

Here is my source code:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>


int main()
{
    #define MAXSIZE 1024

    char workload[MAXSIZE];
    char result[MAXSIZE];
    char buf[10] = {0};
    workload[strlen(workload)] = EOF;
    int workload_size = strlen(workload);

    int fd1[2], fd2[2];
    int n;
    pid_t pid;
    if (pipe(fd1) < 0 || pipe(fd2) < 0) {
        fprintf(stderr, "pipe error: %s\n", strerror(errno));
        exit(1);
    }

    if ((pid = fork()) < 0) {
        fprintf(stderr, "fork error: %s\n", strerror(errno));
        exit(1);
    } else if (pid > 0) {
        close(fd1[0]);
        close(fd2[1]);
        while(fgets(workload, MAXSIZE, stdin) != NULL)
        {
            workload_size = strlen(workload);
            if (write(fd1[1], workload, workload_size) != workload_size) {
                fprintf(stderr, "write to pipe error: %s\n", strerror(errno));
                exit(1);
            }

            if ((n = read(fd2[0], result, MAXSIZE)) < 0) {
                fprintf(stderr, "read from pipe error: %s\n", strerror(errno));
                exit(1);
            }

            if (n == 0) {
                fprintf(stderr, "child closed the pipe\n");
                exit(1);
            }

            result[n] = 0;

            if (puts(result) == EOF) {
                fprintf(stderr, "fputs error\n");
                exit(1);
            }
        }
    } else {
        close(fd1[1]);
        close(fd2[0]);
        if (fd1[0] != STDIN_FILENO) {
            if (dup2(fd1[0] ,STDIN_FILENO) != STDIN_FILENO) {
                fprintf(stderr, "dup2 error to stdin.\n");
                exit(1);
            }
            close(fd1[0]);
        }
        if (fd2[1] != STDOUT_FILENO) {
            if (dup2(fd2[1] ,STDOUT_FILENO) != STDOUT_FILENO) {
                fprintf(stderr, "dup2 error to stdout.\n");
                exit(1);
            }
            close(fd2[1]);
        }

        if (execl("./a.out", "a.out", NULL) < 0) {
            fprintf(stderr, "execl error: %s\n", strerror(errno));
            exit(1);
        }
        exit(0);
    }

    return 0;
}

The child process just read from standard input and output it:

#include <stdio.h>

int main()
{
    #define MAXSIZE 1024
    char x[MAXSIZE];
    int n;
    while(fgets(x, 1024, stdin) != NULL)
    {
        printf("%s", x);
    }
    return 0;
}
like image 721
Bin Wang Avatar asked Jan 01 '26 05:01

Bin Wang


1 Answers

You can use stdbuf utility to change the buffering of your child process.

Or, if you can change the code of the child process, call setvbuf directly from the child process.

like image 145
Maxim Egorushkin Avatar answered Jan 02 '26 19:01

Maxim Egorushkin