Skip to content

Commit

Permalink
unix,stream: fix zero byte writes
Browse files Browse the repository at this point in the history
Fixes a regression where a write request to write a zero byte buffer
would never complete.

Refs: libuv#2097
Refs: libuv#2134
PR-URL: libuv#2149
Reviewed-By: Ben Noordhuis <[email protected]>
  • Loading branch information
santigimeno authored and njlr committed Apr 5, 2019
1 parent 5f3c6e8 commit d04aef9
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/unix/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,13 +745,13 @@ static int uv__write_req_update(uv_stream_t* stream,

buf = req->bufs + req->write_index;

while (n > 0) {
do {
len = n < buf->len ? n : buf->len;
buf->base += len;
buf->len -= len;
buf += (buf->len == 0); /* Advance to next buffer if this one is empty. */
n -= len;
}
} while (n > 0);

req->write_index = buf - req->bufs;

Expand Down Expand Up @@ -897,7 +897,7 @@ static void uv__write(uv_stream_t* stream) {
goto error;
}

if (n > 0 && uv__write_req_update(stream, req, n)) {
if (n >= 0 && uv__write_req_update(stream, req, n)) {
uv__write_req_finish(req);
return; /* TODO(bnoordhuis) Start trying to write the next request. */
}
Expand Down
5 changes: 5 additions & 0 deletions test/run-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ int ipc_helper_tcp_connection(void);
int ipc_helper_closed_handle(void);
int ipc_send_recv_helper(void);
int ipc_helper_bind_twice(void);
int ipc_helper_send_zero(void);
int stdio_over_pipes_helper(void);
int spawn_stdin_stdout(void);
int spawn_tcp_server_helper(void);
Expand Down Expand Up @@ -104,6 +105,10 @@ static int maybe_run_test(int argc, char **argv) {
return ipc_helper_bind_twice();
}

if (strcmp(argv[1], "ipc_helper_send_zero") == 0) {
return ipc_helper_send_zero();
}

if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) {
return stdio_over_pipes_helper();
}
Expand Down
53 changes: 53 additions & 0 deletions test/test-ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static int tcp_conn_read_cb_called;
static int tcp_conn_write_cb_called;
static int closed_handle_data_read;
static int closed_handle_write;
static int send_zero_write;

typedef struct {
uv_connect_t conn_req;
Expand Down Expand Up @@ -431,6 +432,14 @@ static void on_read_closed_handle(uv_stream_t* handle,
#endif


static void on_read_send_zero(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
ASSERT(nread == 0 || nread == UV_EOF);
free(buf->base);
}


static int run_ipc_test(const char* helper, uv_read_cb read_cb) {
uv_process_t process;
int r;
Expand Down Expand Up @@ -555,6 +564,13 @@ TEST_IMPL(ipc_listen_after_bind_twice) {
}
#endif

TEST_IMPL(ipc_send_zero) {
int r;
r = run_ipc_test("ipc_helper_send_zero", on_read_send_zero);
ASSERT(r == 0);
return 0;
}


/* Everything here runs in a child process. */

Expand Down Expand Up @@ -598,6 +614,11 @@ static void closed_handle_write_cb(uv_write_t* req, int status) {
}


static void send_zero_write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
send_zero_write++;
}

static void on_tcp_child_process_read(uv_stream_t* tcp,
ssize_t nread,
const uv_buf_t* buf) {
Expand Down Expand Up @@ -919,3 +940,35 @@ int ipc_helper_bind_twice(void) {
MAKE_VALGRIND_HAPPY();
return 0;
}

int ipc_helper_send_zero(void) {
int r;
uv_buf_t zero_buf;

zero_buf = uv_buf_init(0, 0);

r = uv_pipe_init(uv_default_loop(), &channel, 0);
ASSERT(r == 0);

uv_pipe_open(&channel, 0);

ASSERT(1 == uv_is_readable((uv_stream_t*) &channel));
ASSERT(1 == uv_is_writable((uv_stream_t*) &channel));
ASSERT(0 == uv_is_closing((uv_handle_t*) &channel));

r = uv_write(&write_req,
(uv_stream_t*)&channel,
&zero_buf,
1,
send_zero_write_cb);

ASSERT(r == 0);

r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
ASSERT(r == 0);

ASSERT(send_zero_write == 1);

MAKE_VALGRIND_HAPPY();
return 0;
}
2 changes: 2 additions & 0 deletions test/test-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ TEST_DECLARE (ipc_send_recv_pipe_inprocess)
TEST_DECLARE (ipc_send_recv_tcp)
TEST_DECLARE (ipc_send_recv_tcp_inprocess)
TEST_DECLARE (ipc_tcp_connection)
TEST_DECLARE (ipc_send_zero)
#ifndef _WIN32
TEST_DECLARE (ipc_closed_handle)
#endif
Expand Down Expand Up @@ -515,6 +516,7 @@ TASK_LIST_START
TEST_ENTRY (ipc_send_recv_tcp)
TEST_ENTRY (ipc_send_recv_tcp_inprocess)
TEST_ENTRY (ipc_tcp_connection)
TEST_ENTRY (ipc_send_zero)
#ifndef _WIN32
TEST_ENTRY (ipc_closed_handle)
#endif
Expand Down

0 comments on commit d04aef9

Please sign in to comment.