I'm trying to confirm whether I'm doing something wrong or I'm running
into a limitation. I want to spawn arbitrary shell commands and send
input / capture output.

The typical uv_spawn example (code below) works fine for
non-backgrounded shell commands like these:
    bash -c 'tee'
    bash -c 'cat -'

but "backgrounded" shell commands do not capture input:
    bash -c 'tee &'
    bash -c 'cat - &'

For example, when the sample code below is modified with:
    args[2] = "cat - &";
and invoked with:
    $ echo foo | ./a.out
then "foo" is not printed.

Although intuitively it seems like this "should not" work, the reason
I bothered to ask is that the following *does* work:
    args[2] = "echo foo &";
invoked with:
    $ ./a.out
prints "foo". Here the "backgrounded" output was captured by libuv.
But in the cases above, input does not reach the backgrounded process.

Sample code follows:

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

    void exit_cb(uv_process_t *req, int64_t exit_status, int term_signal) {
        fprintf(stderr, "Process exited with status %" PRId64 ",
            signal %d\n", exit_status, term_signal);
        uv_close((uv_handle_t*) req, NULL);

    int main() {
        uv_loop_t *loop = malloc(sizeof(uv_loop_t));

        char* args[4];
        args[0] = "/bin/bash";
        args[1] = "-c";
        args[2] = "cat - &";
        args[3] = NULL;

        uv_stdio_container_t child_stdio[3];
        child_stdio[0].flags = UV_INHERIT_FD;
        child_stdio[0].data.fd = 0;
        child_stdio[1].flags = UV_INHERIT_FD;
        child_stdio[1].data.fd = 1;
        child_stdio[2].flags = UV_INHERIT_FD;
        child_stdio[2].data.fd = 2;

        uv_process_options_t options = {0};
        options.exit_cb = exit_cb;
        options.file = args[0];
        options.args = args;
        options.stdio_count = 3;
        options.stdio = child_stdio;

        int r;
        uv_process_t child_req = {0};
        if ((r = uv_spawn(loop, &child_req, &options))) {
            fprintf(stderr, "%s\n", uv_strerror(r));
            return 1;
        } else {
            fprintf(stderr, "Launched process with ID %d\n", child_req.pid);

        return uv_run(loop, UV_RUN_DEFAULT);


Compiled with:
    gcc -pthread -fno-omit-frame-pointer -Wall -g main.c
~/libuv/out/Debug/libuv.a -I ~/libuv/include/

Side note: in the actual application, rather than UV_INHERIT_FD I
would want to use (UV_CREATE_PIPE | UV_READABLE_PIPE) and
(UV_CREATE_PIPE | UV_WRITABLE_PIPE) so that application buffers can be
written to the spawned process.

Thanks for your time.

Justin M. Keyes

You received this message because you are subscribed to the Google Groups 
"libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to libuv+unsubscr...@googlegroups.com.
To post to this group, send email to libuv@googlegroups.com.
Visit this group at https://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.

Reply via email to