unix,stream: fix zero byte writes
Fixes a regression where a write request to write a zero byte buffer would never complete. Refs: https://github.com/libuv/libuv/pull/2097 Refs: https://github.com/libuv/libuv/issues/2134 PR-URL: https://github.com/libuv/libuv/pull/2149 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
176db21733
commit
6140507ba7
@ -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;
|
||||
|
||||
@ -897,7 +897,7 @@ start:
|
||||
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. */
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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. */
|
||||
|
||||
@ -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) {
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user