diff --git a/src/unix/stream.c b/src/unix/stream.c index 3e786abe..5ec6bf4d 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -1417,6 +1417,9 @@ int uv_write2(uv_write_t* req, if (uv__stream_fd(stream) < 0) return UV_EBADF; + if (!(stream->flags & UV_STREAM_WRITABLE)) + return -EPIPE; + if (send_handle) { if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) return UV_EINVAL; @@ -1568,6 +1571,9 @@ int uv_read_start(uv_stream_t* stream, if (stream->flags & UV_CLOSING) return UV_EINVAL; + if (!(stream->flags & UV_STREAM_READABLE)) + return -ENOTCONN; + /* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */ diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 96f89312..b991320c 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -158,9 +158,7 @@ int uv__tcp_bind(uv_tcp_t* tcp, if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) return UV_EINVAL; - err = maybe_new_socket(tcp, - addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + err = maybe_new_socket(tcp, addr->sa_family, 0); if (err) return err; @@ -335,14 +333,14 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { if (single_accept) tcp->flags |= UV_TCP_SINGLE_ACCEPT; - flags = UV_STREAM_READABLE; + flags = 0; #if defined(__MVS__) /* on zOS the listen call does not bind automatically if the socket is unbound. Hence the manual binding to an arbitrary port is required to be done manually */ flags |= UV_HANDLE_BOUND; -#endif +#endif err = maybe_new_socket(tcp, AF_INET, flags); if (err) return err; diff --git a/test/test-list.h b/test/test-list.h index ff0a31d1..a5ace534 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -95,6 +95,7 @@ TEST_DECLARE (tcp_bind_error_fault) TEST_DECLARE (tcp_bind_error_inval) TEST_DECLARE (tcp_bind_localhost_ok) TEST_DECLARE (tcp_bind_invalid_flags) +TEST_DECLARE (tcp_bind_writable_flags) TEST_DECLARE (tcp_listen_without_bind) TEST_DECLARE (tcp_connect_error_fault) TEST_DECLARE (tcp_connect_timeout) @@ -535,6 +536,7 @@ TASK_LIST_START TEST_ENTRY (tcp_bind_error_inval) TEST_ENTRY (tcp_bind_localhost_ok) TEST_ENTRY (tcp_bind_invalid_flags) + TEST_ENTRY (tcp_bind_writable_flags) TEST_ENTRY (tcp_listen_without_bind) TEST_ENTRY (tcp_connect_error_fault) TEST_ENTRY (tcp_connect_timeout) diff --git a/test/test-tcp-bind-error.c b/test/test-tcp-bind-error.c index 10ed68e1..1456d081 100644 --- a/test/test-tcp-bind-error.c +++ b/test/test-tcp-bind-error.c @@ -214,3 +214,45 @@ TEST_IMPL(tcp_listen_without_bind) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(tcp_bind_writable_flags) { + struct sockaddr_in addr; + uv_tcp_t server; + uv_buf_t buf; + uv_write_t write_req; + uv_shutdown_t shutdown_req; + int r; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); + ASSERT(r == 0); + r = uv_listen((uv_stream_t*)&server, 128, NULL); + ASSERT(r == 0); + + ASSERT(0 == uv_is_writable((uv_stream_t*) &server)); + ASSERT(0 == uv_is_readable((uv_stream_t*) &server)); + + buf = uv_buf_init("PING", 4); + r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL); + ASSERT(r == UV_EPIPE); + r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); +#ifdef _WIN32 + ASSERT(r == UV_EPIPE); +#else + ASSERT(r == UV_ENOTCONN); +#endif + r = uv_read_start((uv_stream_t*) &server, NULL, NULL); + ASSERT(r == UV_ENOTCONN); + + uv_close((uv_handle_t*)&server, close_cb); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +}