joyent / libuv

Go to
https://github.com/libuv/libuv
3.27k stars 654 forks source link

Using tty with stdin may trigger an internal abort #988

Open alexcrichton opened 10 years ago

alexcrichton commented 10 years ago
#include <assert.h>                                                    
#include <uv.h>                                                        
#include <stdio.h>                                                     
#include <string.h>                                                    
#include <stdlib.h>                                                    

uv_loop_t *loop;                                                       
uv_tty_t tty;                                                          

void alloc(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) {     
    buf->len = 1024;                                                   
    buf->base = malloc(1024);                                          
}                                                                      

void myread(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { 
    printf("read %d bytes\n", (int) nread);                            
}                                                                      

int main() {                                                           
    loop = uv_default_loop();                                          

    uv_tty_init(loop, &tty, 0, 1);                                     
    uv_read_start((uv_stream_t*) &tty, alloc, myread);                 
    return uv_run(loop, UV_RUN_DEFAULT);                               
}                                                                      

On linux, if this program is compiled and run like ./foo < any_file at the command line, it will cause an abort in uv's event loop. This works fine if you run echo foo | /foo or have stdin attached to a terminal.

I'm not sure if you're supposed to be able to even do this? I get the same abort if a uv_pipe_t is used to read stdin, but it works to call uv_fs_read on stdin in this case.

bnoordhuis commented 10 years ago

It's not a libuv bug but maybe libuv could report the error a little nicer.

What happens is that epoll_ctl() returns EPERM when libuv tries to add the file descriptor and it's not equipped to deal with that.

Standard operating procedure is to check the file type with uv_guess_handle() first, then branch accordingly.

alexcrichton commented 10 years ago

Ah ok, the logic I was using was "fall back to using fs operations only if tty creation fails". Thanks for the clarification!