Hi,

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));
        uv_loop_init(loop);

        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