Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deadlock if synchronous subprocess fills pipe #82

Open
rongcuid opened this issue Feb 19, 2024 · 4 comments
Open

Deadlock if synchronous subprocess fills pipe #82

rongcuid opened this issue Feb 19, 2024 · 4 comments

Comments

@rongcuid
Copy link

If a subprocess outputs large amount of data, it deadlocks both parent and subprocess due to pipe blocking:

#include <stdlib.h>
#include <stdio.h>

#include "subprocess.h"

int main() {
    const char *command_line[] = {"dd", "if=/dev/zero", "bs=1k", "count=65", NULL};
    struct subprocess_s process;
    int result = subprocess_create(command_line, subprocess_option_search_user_path, &process);
    if (result) {
        fprintf(stderr, "Failed to create subprocess: %d\n", result);
        return 1;
    }
    int proc_return;
    result = subprocess_join(&process, &proc_return);
    if (result) {
        fprintf(stderr, "Failed to join subprocess\n");
        return 1;
    }
    printf("Subprocess returned %d\n", proc_return);
    result = subprocess_destroy(&process);
    if (result) {
        fprintf(stderr, "Failed to join subprocess\n");
        return 1;
    }
    return 0;
}

Notice that subprocess dd writes 65k data to stdout, which is greater than Linux's default pipe buffer size, thus blocking the child. However, since subprocess_read_stdout must be used after joining, the parent process cannot progress either, as it can neither drain the pipe nor wait for child to finish.

@sheredom
Copy link
Owner

I can't think of a better solution than to advise you use async. I don't really want to start spawning threads behind your back to handle this kind of thing (and don't know of another way to generally fix this!).

@rongcuid
Copy link
Author

For my case, I am actually not using the outputs. So it might be good to allow ignoring stdout/stderr.

Actually, did I misunderstand something? It seems like I can read from stdout before I join. At least it works on Linux.

@sheredom
Copy link
Owner

I might be able to add an option to ignore stdout/stderr aye.

You should be able to read before join iirc, its just that if you don't have enough data to read it could block forever.

@rongcuid
Copy link
Author

I thought it should return EOF?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants