diff --git a/src/uv-unix.c b/src/uv-unix.c index f35cc6f0..2ee2f864 100644 --- a/src/uv-unix.c +++ b/src/uv-unix.c @@ -481,14 +481,27 @@ out: int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { int r; - - assert(tcp->fd >= 0); + int fd; if (tcp->delayed_error) { uv_err_new((uv_handle_t*)tcp, tcp->delayed_error); return -1; } + if (tcp->fd <= 0) { + if ((fd = uv__socket(AF_INET, SOCK_STREAM, 0)) == -1) { + uv_err_new((uv_handle_t*)tcp, errno); + return -1; + } + + if (uv__stream_open(tcp, fd)) { + close(fd); + return -1; + } + } + + assert(tcp->fd >= 0); + r = listen(tcp->fd, backlog); if (r < 0) { uv_err_new((uv_handle_t*)tcp, errno); diff --git a/test/test-bind-error.c b/test/test-bind-error.c index 4ac60654..f3db848a 100644 --- a/test/test-bind-error.c +++ b/test/test-bind-error.c @@ -188,3 +188,15 @@ TEST_IMPL(bind_localhost_ok) { return 0; } + + +TEST_IMPL(listen_without_bind) { + int r; + uv_tcp_t server; + + uv_init(); + r = uv_tcp_init(&server); + ASSERT(r == 0); + r = uv_tcp_listen(&server, 128, NULL); + ASSERT(r == 0); +} diff --git a/test/test-list.h b/test/test-list.h index 919d7b76..2a7e5676 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -30,6 +30,7 @@ TEST_DECLARE (bind_error_addrnotavail_2) TEST_DECLARE (bind_error_fault) TEST_DECLARE (bind_error_inval) TEST_DECLARE (bind_localhost_ok) +TEST_DECLARE (listen_without_bind) TEST_DECLARE (bind6_error_addrinuse) TEST_DECLARE (bind6_error_addrnotavail) TEST_DECLARE (bind6_error_fault) @@ -82,6 +83,7 @@ TASK_LIST_START TEST_ENTRY (bind_error_fault) TEST_ENTRY (bind_error_inval) TEST_ENTRY (bind_localhost_ok) + TEST_ENTRY (listen_without_bind) TEST_ENTRY (bind6_error_addrinuse) TEST_ENTRY (bind6_error_addrnotavail)