2013-02-07 37 views
9

Tôi đang sử dụng libuv. Tôi đã đọc http://nikhilm.github.com/uvbook/processes.html và vẫn không thể tìm ra cách nắm bắt stdout của một tiến trình con để nó có sẵn trong cha mẹ (nhưng không phải ở vị trí của stdin của cha).Chụp hình dáng của quá trình con bằng libuv

Mã của tôi hiện nay là:

#include <stdio.h> 
#include <stdlib.h> 
#include "../../libuv/include/uv.h" 

uv_loop_t *loop; 
uv_process_t child_req; 
uv_process_options_t options; 
uv_pipe_t apipe; 

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

uv_buf_t alloc_buffer(uv_handle_t *handle, size_t len) { 
    printf("alloc_buffer called\n"); 
    uv_buf_t buf; 
    buf.base = malloc(len); 
    buf.len = len; 
    return buf; 
} 

void read_apipe(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) { 
    printf("read %li bytes from the child process\n", nread); 
} 

int main(int argc, char *argv[]) { 
    printf("spawn_test\n"); 
    loop = uv_default_loop(); 

    char* args[3]; 
    args[0] = "dummy"; 
    args[1] = NULL; 
    args[2] = NULL; 

    uv_pipe_init(loop, &apipe, 0); 
    uv_pipe_open(&apipe, 0); 

    options.stdio_count = 3; 
    uv_stdio_container_t child_stdio[3]; 
    child_stdio[0].flags = UV_IGNORE; 
    child_stdio[1].flags = UV_INHERIT_STREAM; 
    child_stdio[1].data.stream = (uv_stream_t *) &apipe; 
    child_stdio[2].flags = UV_IGNORE; 
    options.stdio = child_stdio; 

    options.exit_cb = on_child_exit; 
    options.file = args[0]; 
    options.args = args; 

    uv_read_start((uv_stream_t*)&apipe, alloc_buffer, read_apipe); 
    if (uv_spawn(loop, &child_req, options)) { 
     fprintf(stderr, "%s\n", uv_strerror(uv_last_error(loop))); 
     return 1; 
    } 

    return uv_run(loop, UV_RUN_DEFAULT); 
} 

dummy.c:

#include <unistd.h> 
#include <stdio.h> 

int main() { 
    printf("child starting\n"); 
    sleep(1); 
    printf("child running\n"); 
    sleep(2); 
    printf("child ending\n"); 
    return 0; 
} 

Tôi có cảm giác dai dẳng rằng tôi không hoàn toàn hiểu được quan điểm của ống libuv của được nêu ra.

Trả lời

5

tôi đã tìm thấy các giải pháp:

  1. tôi đã có cờ sai, họ cần phải có được UV_CREATE_PIPE | UV_READABLE_PIPE không UV_INHERIT_STREAM.
  2. Tôi cần gọi uv_read_start sau uv_spawn. Tôi cho rằng không có cơ hội mất dữ liệu, vì uv_run vẫn chưa được gọi.
  3. Hai bản sửa lỗi trên cho thấy tất cả đầu ra từ dummy để đến cùng một lúc, thay vì trong ba khối (như trên dòng lệnh). An fflush in dummy.c sửa lỗi này.

spawn_test:

#include <stdio.h> 
#include <stdlib.h> 
#include "../../libuv/include/uv.h" 

uv_loop_t *loop; 
uv_process_t child_req; 
uv_process_options_t options; 
uv_pipe_t apipe; 

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

uv_buf_t alloc_buffer(uv_handle_t *handle, size_t len) { 
    printf("alloc_buffer called, requesting a %lu byte buffer\n"); 
    uv_buf_t buf; 
    buf.base = malloc(len); 
    buf.len = len; 
    return buf; 
} 

void read_apipe(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) { 
    printf("read %li bytes in a %lu byte buffer\n", nread, buf.len); 
    if (nread + 1 > buf.len) return; 
    buf.base[nread] = '\0'; // turn it into a cstring 
    printf("read: |%s|", buf.base); 
} 

int main(int argc, char *argv[]) { 
    printf("spawn_test\n"); 
    loop = uv_default_loop(); 

    char* args[3]; 
    args[0] = "dummy"; 
    args[1] = NULL; 
    args[2] = NULL; 

    uv_pipe_init(loop, &apipe, 0); 
    uv_pipe_open(&apipe, 0); 

    options.stdio_count = 3; 
    uv_stdio_container_t child_stdio[3]; 
    child_stdio[0].flags = UV_IGNORE; 
    child_stdio[1].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; 
    child_stdio[1].data.stream = (uv_stream_t *) &apipe; 
    child_stdio[2].flags = UV_IGNORE; 
    options.stdio = child_stdio; 

    options.exit_cb = on_child_exit; 
    options.file = args[0]; 
    options.args = args; 

    if (uv_spawn(loop, &child_req, options)) { 
     fprintf(stderr, "%s\n", uv_strerror(uv_last_error(loop))); 
     return 1; 
    } 
    uv_read_start((uv_stream_t*)&apipe, alloc_buffer, read_apipe); 

    return uv_run(loop, UV_RUN_DEFAULT); 
} 

dummy.c:

#include <unistd.h> 
#include <stdio.h> 

int main() { 
    printf("child starting\n"); 
    fflush(stdout); 
    sleep(1); 
    printf("child running\n"); 
    fflush(stdout); 
    sleep(2); 
    printf("child ending\n"); 
    fflush(stdout); 
    return 0; 
} 
4

Xem cách họ làm điều đó trong đơn vị kiểm tra libuv libuv/test/test-stdio-over-pipes.c:

  • Đừng gọi uv_pipe_open
  • Flags cho stdin của con: UV_CREATE_PIPE | UV_READABLE_PIPE
  • Flags cho stdout và stderr của con: UV_CREATE_PIPE | UV_WRITABLE_PIPE

Ngoài ra còn có một issue trên Windows, nơi uv_spawn có thể quay trở lại bằng không mặc dù nó gặp phải một lỗi, và trong những trường hợp, bạn cần kiểm tra process.spawn_error, chỉ tồn tại trên Windows.

Các vấn đề liên quan