req: revisions to uv_req_t handling

- Remove the `active_reqs` queue, which is never used. There are more
   efficient per-stream queues that `libuv` uses whenever it needs this
   information, so duplicating it and managing it here seems
   like unnecessary extra space and work.
 - Unix `uv_loop_init` didn't explicitly initialize.
   `loop->active_handles` (although it did memset the whole struct
   to 0, so it wasn't wrong previously, just inconsistent).
 - Consolidate repeated code for `uv__has_active_reqs`.
 - Change `uv__loop_alive` to use the helper functions (mirroring the
   unix copy of the same function).
 - Initialize some more uv_stream_t fields in init, rather than waiting
   for the connection callback. This helps surface bugs in libuv or the
   caller better, since it ensures libuv doesn't see uninitialized
   memory if asked to look at these fields before it thinks the socket
   is connected.
 - Fixes what appears to be a double-counting of `handle->reqs_pending`,
   in the highly-unlikely event that the code wants to emulate IOCP,
   but `RegisterWaitForSingleObject` somehow managed to fail.

PR-URL: https://github.com/libuv/libuv/pull/1746
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
Jameson Nash 2017-11-14 17:46:50 -05:00 committed by Santiago Gimeno
parent 8f9ba2a597
commit 88c2af0e65
No known key found for this signature in database
GPG Key ID: F28C3C8DA33C03BE
8 changed files with 20 additions and 18 deletions

View File

@ -378,8 +378,7 @@ UV_EXTERN const char* uv_err_name(int err);
/* read-only */ \
uv_req_type type; \
/* private */ \
void* active_queue[2]; \
void* reserved[4]; \
void* reserved[6]; \
UV_REQ_PRIVATE_FIELDS \
/* Abstract base class of all requests. */
@ -1531,7 +1530,10 @@ struct uv_loop_s {
/* Loop reference counting. */
unsigned int active_handles;
void* handle_queue[2];
void* active_reqs[2];
union {
void* unused[2];
unsigned int count;
} active_reqs;
/* Internal flag to signal loop stop. */
unsigned int stop_flag;
UV_LOOP_PRIVATE_FIELDS

View File

@ -38,13 +38,14 @@ int uv_loop_init(uv_loop_t* loop) {
heap_init((struct heap*) &loop->timer_heap);
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->active_reqs);
QUEUE_INIT(&loop->idle_handles);
QUEUE_INIT(&loop->async_handles);
QUEUE_INIT(&loop->check_handles);
QUEUE_INIT(&loop->prepare_handles);
QUEUE_INIT(&loop->handle_queue);
loop->active_handles = 0;
loop->active_reqs.count = 0;
loop->nfds = 0;
loop->watchers = NULL;
loop->nwatchers = 0;

View File

@ -627,7 +627,7 @@ int uv_loop_close(uv_loop_t* loop) {
void* saved_data;
#endif
if (!QUEUE_EMPTY(&(loop)->active_reqs))
if (uv__has_active_reqs(loop))
return UV_EBUSY;
QUEUE_FOREACH(q, &loop->handle_queue) {

View File

@ -133,18 +133,18 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
void uv__fs_scandir_cleanup(uv_fs_t* req);
#define uv__has_active_reqs(loop) \
(QUEUE_EMPTY(&(loop)->active_reqs) == 0)
((loop)->active_reqs.count > 0)
#define uv__req_register(loop, req) \
do { \
QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \
(loop)->active_reqs.count++; \
} \
while (0)
#define uv__req_unregister(loop, req) \
do { \
assert(uv__has_active_reqs(loop)); \
QUEUE_REMOVE(&(req)->active_queue); \
(loop)->active_reqs.count--; \
} \
while (0)

View File

@ -239,7 +239,7 @@ int uv_loop_init(uv_loop_t* loop) {
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->handle_queue);
QUEUE_INIT(&loop->active_reqs);
loop->active_reqs.count = 0;
loop->active_handles = 0;
loop->pending_reqs_tail = NULL;
@ -470,8 +470,8 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
static int uv__loop_alive(const uv_loop_t* loop) {
return loop->active_handles > 0 ||
!QUEUE_EMPTY(&loop->active_reqs) ||
return uv__has_active_handles(loop) ||
uv__has_active_reqs(loop) ||
loop->endgame_handles != NULL;
}

View File

@ -847,6 +847,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
return;
}
/* Wait for completion via IOCP */
handle->reqs_pending++;
}

View File

@ -37,11 +37,6 @@ INLINE static void uv_stream_init(uv_loop_t* loop,
handle->write_queue_size = 0;
handle->activecnt = 0;
handle->stream.conn.shutdown_req = NULL;
}
INLINE static void uv_connection_init(uv_stream_t* handle) {
handle->flags |= UV_HANDLE_CONNECTION;
handle->stream.conn.write_reqs_pending = 0;
UV_REQ_INIT(&handle->read_req, UV_READ);
@ -51,4 +46,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
}
INLINE static void uv_connection_init(uv_stream_t* handle) {
handle->flags |= UV_HANDLE_CONNECTION;
}
#endif /* UV_WIN_STREAM_INL_H_ */

View File

@ -459,8 +459,6 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
handle->reqs_pending++;
return;
}
} else {
/* Make this req pending reporting an error. */