uv_spawn: read/write to/from a "backgrounded" shell command

189 views
Skip to first unread message

Justin M. Keyes

unread,
Oct 18, 2016, 9:48:32 AM10/18/16
to li...@googlegroups.com
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

Justin M. Keyes

unread,
Oct 18, 2016, 9:48:36 AM10/18/16
to li...@googlegroups.com
On Tue, Oct 18, 2016 at 12:47 PM, Justin M. Keyes <just...@gmail.com> wrote:
> 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.

Gah, I had tunnel-vision here. Of course, these invocations behave the
same way (no output):

$ echo foo|bash -c 'tee &'
$ echo foo|bash -c 'cat - &'

So that is out of libuv's hands.

Though if anyone has insight into how or whether the streams can be
redirected (in libuv) so that input reaches the backgrounded process
(and its output is captured), that would be great.

---
Justin M. Keyes
Reply all
Reply to author
Forward
0 new messages