1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
29 #include <crtdbg.h>
30 #endif
31
32 #include "uv.h"
33 #include "internal.h"
34 #include "queue.h"
35 #include "handle-inl.h"
36 #include "heap-inl.h"
37 #include "req-inl.h"
38
39 /* uv_once initialization guards */
40 static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
41
42
43 #if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))
44 /* Our crt debug report handler allows us to temporarily disable asserts
45 * just for the current thread.
46 */
47
48 UV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE;
49
uv__crt_dbg_report_handler(int report_type,char * message,int * ret_val)50 static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) {
51 if (uv__crt_assert_enabled || report_type != _CRT_ASSERT)
52 return FALSE;
53
54 if (ret_val) {
55 /* Set ret_val to 0 to continue with normal execution.
56 * Set ret_val to 1 to trigger a breakpoint.
57 */
58
59 if(IsDebuggerPresent())
60 *ret_val = 1;
61 else
62 *ret_val = 0;
63 }
64
65 /* Don't call _CrtDbgReport. */
66 return TRUE;
67 }
68 #else
69 UV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE;
70 #endif
71
72
73 #if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
uv__crt_invalid_parameter_handler(const wchar_t * expression,const wchar_t * function,const wchar_t * file,unsigned int line,uintptr_t reserved)74 static void uv__crt_invalid_parameter_handler(const wchar_t* expression,
75 const wchar_t* function, const wchar_t * file, unsigned int line,
76 uintptr_t reserved) {
77 /* No-op. */
78 }
79 #endif
80
81 static uv_loop_t** uv__loops;
82 static int uv__loops_size;
83 static int uv__loops_capacity;
84 #define UV__LOOPS_CHUNK_SIZE 8
85 static uv_mutex_t uv__loops_lock;
86
uv__loops_init(void)87 static void uv__loops_init(void) {
88 uv_mutex_init(&uv__loops_lock);
89 }
90
uv__loops_add(uv_loop_t * loop)91 static int uv__loops_add(uv_loop_t* loop) {
92 uv_loop_t** new_loops;
93 int new_capacity, i;
94
95 uv_mutex_lock(&uv__loops_lock);
96
97 if (uv__loops_size == uv__loops_capacity) {
98 new_capacity = uv__loops_capacity + UV__LOOPS_CHUNK_SIZE;
99 new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * new_capacity);
100 if (!new_loops)
101 goto failed_loops_realloc;
102 uv__loops = new_loops;
103 for (i = uv__loops_capacity; i < new_capacity; ++i)
104 uv__loops[i] = NULL;
105 uv__loops_capacity = new_capacity;
106 }
107 uv__loops[uv__loops_size] = loop;
108 ++uv__loops_size;
109
110 uv_mutex_unlock(&uv__loops_lock);
111 return 0;
112
113 failed_loops_realloc:
114 uv_mutex_unlock(&uv__loops_lock);
115 return ERROR_OUTOFMEMORY;
116 }
117
uv__loops_remove(uv_loop_t * loop)118 static void uv__loops_remove(uv_loop_t* loop) {
119 int loop_index;
120 int smaller_capacity;
121 uv_loop_t** new_loops;
122
123 uv_mutex_lock(&uv__loops_lock);
124
125 for (loop_index = 0; loop_index < uv__loops_size; ++loop_index) {
126 if (uv__loops[loop_index] == loop)
127 break;
128 }
129 /* If loop was not found, ignore */
130 if (loop_index == uv__loops_size)
131 goto loop_removed;
132
133 uv__loops[loop_index] = uv__loops[uv__loops_size - 1];
134 uv__loops[uv__loops_size - 1] = NULL;
135 --uv__loops_size;
136
137 if (uv__loops_size == 0) {
138 uv__loops_capacity = 0;
139 uv__free(uv__loops);
140 uv__loops = NULL;
141 goto loop_removed;
142 }
143
144 /* If we didn't grow to big skip downsizing */
145 if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE)
146 goto loop_removed;
147
148 /* Downsize only if more than half of buffer is free */
149 smaller_capacity = uv__loops_capacity / 2;
150 if (uv__loops_size >= smaller_capacity)
151 goto loop_removed;
152 new_loops = uv__realloc(uv__loops, sizeof(uv_loop_t*) * smaller_capacity);
153 if (!new_loops)
154 goto loop_removed;
155 uv__loops = new_loops;
156 uv__loops_capacity = smaller_capacity;
157
158 loop_removed:
159 uv_mutex_unlock(&uv__loops_lock);
160 }
161
uv__wake_all_loops(void)162 void uv__wake_all_loops(void) {
163 int i;
164 uv_loop_t* loop;
165
166 uv_mutex_lock(&uv__loops_lock);
167 for (i = 0; i < uv__loops_size; ++i) {
168 loop = uv__loops[i];
169 assert(loop);
170 if (loop->iocp != INVALID_HANDLE_VALUE)
171 PostQueuedCompletionStatus(loop->iocp, 0, 0, NULL);
172 }
173 uv_mutex_unlock(&uv__loops_lock);
174 }
175
uv_init(void)176 static void uv_init(void) {
177 /* Tell Windows that we will handle critical errors. */
178 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
179 SEM_NOOPENFILEERRORBOX);
180
181 /* Tell the CRT to not exit the application when an invalid parameter is
182 * passed. The main issue is that invalid FDs will trigger this behavior.
183 */
184 #if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
185 _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);
186 #endif
187
188 /* We also need to setup our debug report handler because some CRT
189 * functions (eg _get_osfhandle) raise an assert when called with invalid
190 * FDs even though they return the proper error code in the release build.
191 */
192 #if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))
193 _CrtSetReportHook(uv__crt_dbg_report_handler);
194 #endif
195
196 /* Initialize tracking of all uv loops */
197 uv__loops_init();
198
199 /* Fetch winapi function pointers. This must be done first because other
200 * initialization code might need these function pointers to be loaded.
201 */
202 uv_winapi_init();
203
204 /* Initialize winsock */
205 uv_winsock_init();
206
207 /* Initialize FS */
208 uv_fs_init();
209
210 /* Initialize signal stuff */
211 uv_signals_init();
212
213 /* Initialize console */
214 uv_console_init();
215
216 /* Initialize utilities */
217 uv__util_init();
218
219 /* Initialize system wakeup detection */
220 uv__init_detect_system_wakeup();
221 }
222
223
uv_loop_init(uv_loop_t * loop)224 int uv_loop_init(uv_loop_t* loop) {
225 struct heap* timer_heap;
226 int err;
227
228 /* Initialize libuv itself first */
229 uv__once_init();
230
231 /* Create an I/O completion port */
232 loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
233 if (loop->iocp == NULL)
234 return uv_translate_sys_error(GetLastError());
235
236 /* To prevent uninitialized memory access, loop->time must be initialized
237 * to zero before calling uv_update_time for the first time.
238 */
239 loop->time = 0;
240 uv_update_time(loop);
241
242 QUEUE_INIT(&loop->wq);
243 QUEUE_INIT(&loop->handle_queue);
244 loop->active_reqs.count = 0;
245 loop->active_handles = 0;
246
247 loop->pending_reqs_tail = NULL;
248
249 loop->endgame_handles = NULL;
250
251 loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap));
252 if (timer_heap == NULL) {
253 err = UV_ENOMEM;
254 goto fail_timers_alloc;
255 }
256
257 heap_init(timer_heap);
258
259 loop->check_handles = NULL;
260 loop->prepare_handles = NULL;
261 loop->idle_handles = NULL;
262
263 loop->next_prepare_handle = NULL;
264 loop->next_check_handle = NULL;
265 loop->next_idle_handle = NULL;
266
267 memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets);
268
269 loop->active_tcp_streams = 0;
270 loop->active_udp_streams = 0;
271
272 loop->timer_counter = 0;
273 loop->stop_flag = 0;
274
275 err = uv_mutex_init(&loop->wq_mutex);
276 if (err)
277 goto fail_mutex_init;
278
279 err = uv_async_init(loop, &loop->wq_async, uv__work_done);
280 if (err)
281 goto fail_async_init;
282
283 uv__handle_unref(&loop->wq_async);
284 loop->wq_async.flags |= UV_HANDLE_INTERNAL;
285
286 err = uv__loops_add(loop);
287 if (err)
288 goto fail_async_init;
289
290 return 0;
291
292 fail_async_init:
293 uv_mutex_destroy(&loop->wq_mutex);
294
295 fail_mutex_init:
296 uv__free(timer_heap);
297 loop->timer_heap = NULL;
298
299 fail_timers_alloc:
300 CloseHandle(loop->iocp);
301 loop->iocp = INVALID_HANDLE_VALUE;
302
303 return err;
304 }
305
306
uv_update_time(uv_loop_t * loop)307 void uv_update_time(uv_loop_t* loop) {
308 uint64_t new_time = uv__hrtime(1000);
309 assert(new_time >= loop->time);
310 loop->time = new_time;
311 }
312
313
uv__once_init(void)314 void uv__once_init(void) {
315 uv_once(&uv_init_guard_, uv_init);
316 }
317
318
uv__loop_close(uv_loop_t * loop)319 void uv__loop_close(uv_loop_t* loop) {
320 size_t i;
321
322 uv__loops_remove(loop);
323
324 /* Close the async handle without needing an extra loop iteration.
325 * We might have a pending message, but we're just going to destroy the IOCP
326 * soon, so we can just discard it now without the usual risk of a getting
327 * another notification from GetQueuedCompletionStatusEx after calling the
328 * close_cb (which we also skip defining). We'll assert later that queue was
329 * actually empty and all reqs handled. */
330 loop->wq_async.async_sent = 0;
331 loop->wq_async.close_cb = NULL;
332 uv__handle_closing(&loop->wq_async);
333 uv__handle_close(&loop->wq_async);
334
335 for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
336 SOCKET sock = loop->poll_peer_sockets[i];
337 if (sock != 0 && sock != INVALID_SOCKET)
338 closesocket(sock);
339 }
340
341 uv_mutex_lock(&loop->wq_mutex);
342 assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");
343 assert(!uv__has_active_reqs(loop));
344 uv_mutex_unlock(&loop->wq_mutex);
345 uv_mutex_destroy(&loop->wq_mutex);
346
347 uv__free(loop->timer_heap);
348 loop->timer_heap = NULL;
349
350 CloseHandle(loop->iocp);
351 }
352
353
uv__loop_configure(uv_loop_t * loop,uv_loop_option option,va_list ap)354 int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
355 return UV_ENOSYS;
356 }
357
358
uv_backend_fd(const uv_loop_t * loop)359 int uv_backend_fd(const uv_loop_t* loop) {
360 return -1;
361 }
362
363
uv_loop_fork(uv_loop_t * loop)364 int uv_loop_fork(uv_loop_t* loop) {
365 return UV_ENOSYS;
366 }
367
368
uv_backend_timeout(const uv_loop_t * loop)369 int uv_backend_timeout(const uv_loop_t* loop) {
370 if (loop->stop_flag != 0)
371 return 0;
372
373 if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
374 return 0;
375
376 if (loop->pending_reqs_tail)
377 return 0;
378
379 if (loop->endgame_handles)
380 return 0;
381
382 if (loop->idle_handles)
383 return 0;
384
385 return uv__next_timeout(loop);
386 }
387
388
uv__poll_wine(uv_loop_t * loop,DWORD timeout)389 static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
390 DWORD bytes;
391 ULONG_PTR key;
392 OVERLAPPED* overlapped;
393 uv_req_t* req;
394 int repeat;
395 uint64_t timeout_time;
396
397 timeout_time = loop->time + timeout;
398
399 for (repeat = 0; ; repeat++) {
400 GetQueuedCompletionStatus(loop->iocp,
401 &bytes,
402 &key,
403 &overlapped,
404 timeout);
405
406 if (overlapped) {
407 /* Package was dequeued */
408 req = uv_overlapped_to_req(overlapped);
409 uv_insert_pending_req(loop, req);
410
411 /* Some time might have passed waiting for I/O,
412 * so update the loop time here.
413 */
414 uv_update_time(loop);
415 } else if (GetLastError() != WAIT_TIMEOUT) {
416 /* Serious error */
417 uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
418 } else if (timeout > 0) {
419 /* GetQueuedCompletionStatus can occasionally return a little early.
420 * Make sure that the desired timeout target time is reached.
421 */
422 uv_update_time(loop);
423 if (timeout_time > loop->time) {
424 timeout = (DWORD)(timeout_time - loop->time);
425 /* The first call to GetQueuedCompletionStatus should return very
426 * close to the target time and the second should reach it, but
427 * this is not stated in the documentation. To make sure a busy
428 * loop cannot happen, the timeout is increased exponentially
429 * starting on the third round.
430 */
431 timeout += repeat ? (1 << (repeat - 1)) : 0;
432 continue;
433 }
434 }
435 break;
436 }
437 }
438
439
uv__poll(uv_loop_t * loop,DWORD timeout)440 static void uv__poll(uv_loop_t* loop, DWORD timeout) {
441 BOOL success;
442 uv_req_t* req;
443 OVERLAPPED_ENTRY overlappeds[128];
444 ULONG count;
445 ULONG i;
446 int repeat;
447 uint64_t timeout_time;
448
449 timeout_time = loop->time + timeout;
450
451 for (repeat = 0; ; repeat++) {
452 success = GetQueuedCompletionStatusEx(loop->iocp,
453 overlappeds,
454 ARRAY_SIZE(overlappeds),
455 &count,
456 timeout,
457 FALSE);
458
459 if (success) {
460 for (i = 0; i < count; i++) {
461 /* Package was dequeued, but see if it is not a empty package
462 * meant only to wake us up.
463 */
464 if (overlappeds[i].lpOverlapped) {
465 req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
466 uv_insert_pending_req(loop, req);
467 }
468 }
469
470 /* Some time might have passed waiting for I/O,
471 * so update the loop time here.
472 */
473 uv_update_time(loop);
474 } else if (GetLastError() != WAIT_TIMEOUT) {
475 /* Serious error */
476 uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
477 } else if (timeout > 0) {
478 /* GetQueuedCompletionStatus can occasionally return a little early.
479 * Make sure that the desired timeout target time is reached.
480 */
481 uv_update_time(loop);
482 if (timeout_time > loop->time) {
483 timeout = (DWORD)(timeout_time - loop->time);
484 /* The first call to GetQueuedCompletionStatus should return very
485 * close to the target time and the second should reach it, but
486 * this is not stated in the documentation. To make sure a busy
487 * loop cannot happen, the timeout is increased exponentially
488 * starting on the third round.
489 */
490 timeout += repeat ? (1 << (repeat - 1)) : 0;
491 continue;
492 }
493 }
494 break;
495 }
496 }
497
498
uv__loop_alive(const uv_loop_t * loop)499 static int uv__loop_alive(const uv_loop_t* loop) {
500 return uv__has_active_handles(loop) ||
501 uv__has_active_reqs(loop) ||
502 loop->endgame_handles != NULL;
503 }
504
505
uv_loop_alive(const uv_loop_t * loop)506 int uv_loop_alive(const uv_loop_t* loop) {
507 return uv__loop_alive(loop);
508 }
509
510
uv_run(uv_loop_t * loop,uv_run_mode mode)511 int uv_run(uv_loop_t *loop, uv_run_mode mode) {
512 DWORD timeout;
513 int r;
514 int ran_pending;
515
516 r = uv__loop_alive(loop);
517 if (!r)
518 uv_update_time(loop);
519
520 while (r != 0 && loop->stop_flag == 0) {
521 uv_update_time(loop);
522 uv__run_timers(loop);
523
524 ran_pending = uv_process_reqs(loop);
525 uv_idle_invoke(loop);
526 uv_prepare_invoke(loop);
527
528 timeout = 0;
529 if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
530 timeout = uv_backend_timeout(loop);
531
532 if (pGetQueuedCompletionStatusEx)
533 uv__poll(loop, timeout);
534 else
535 uv__poll_wine(loop, timeout);
536
537
538 uv_check_invoke(loop);
539 uv_process_endgames(loop);
540
541 if (mode == UV_RUN_ONCE) {
542 /* UV_RUN_ONCE implies forward progress: at least one callback must have
543 * been invoked when it returns. uv__io_poll() can return without doing
544 * I/O (meaning: no callbacks) when its timeout expires - which means we
545 * have pending timers that satisfy the forward progress constraint.
546 *
547 * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
548 * the check.
549 */
550 uv__run_timers(loop);
551 }
552
553 r = uv__loop_alive(loop);
554 if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
555 break;
556 }
557
558 /* The if statement lets the compiler compile it to a conditional store.
559 * Avoids dirtying a cache line.
560 */
561 if (loop->stop_flag != 0)
562 loop->stop_flag = 0;
563
564 return r;
565 }
566
567
uv_fileno(const uv_handle_t * handle,uv_os_fd_t * fd)568 int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
569 uv_os_fd_t fd_out;
570
571 switch (handle->type) {
572 case UV_TCP:
573 fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket;
574 break;
575
576 case UV_NAMED_PIPE:
577 fd_out = ((uv_pipe_t*) handle)->handle;
578 break;
579
580 case UV_TTY:
581 fd_out = ((uv_tty_t*) handle)->handle;
582 break;
583
584 case UV_UDP:
585 fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket;
586 break;
587
588 case UV_POLL:
589 fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket;
590 break;
591
592 default:
593 return UV_EINVAL;
594 }
595
596 if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE)
597 return UV_EBADF;
598
599 *fd = fd_out;
600 return 0;
601 }
602
603
uv__socket_sockopt(uv_handle_t * handle,int optname,int * value)604 int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
605 int r;
606 int len;
607 SOCKET socket;
608
609 if (handle == NULL || value == NULL)
610 return UV_EINVAL;
611
612 if (handle->type == UV_TCP)
613 socket = ((uv_tcp_t*) handle)->socket;
614 else if (handle->type == UV_UDP)
615 socket = ((uv_udp_t*) handle)->socket;
616 else
617 return UV_ENOTSUP;
618
619 len = sizeof(*value);
620
621 if (*value == 0)
622 r = getsockopt(socket, SOL_SOCKET, optname, (char*) value, &len);
623 else
624 r = setsockopt(socket, SOL_SOCKET, optname, (const char*) value, len);
625
626 if (r == SOCKET_ERROR)
627 return uv_translate_sys_error(WSAGetLastError());
628
629 return 0;
630 }
631
uv_cpumask_size(void)632 int uv_cpumask_size(void) {
633 return (int)(sizeof(DWORD_PTR) * 8);
634 }
635
uv__getsockpeername(const uv_handle_t * handle,uv__peersockfunc func,struct sockaddr * name,int * namelen,int delayed_error)636 int uv__getsockpeername(const uv_handle_t* handle,
637 uv__peersockfunc func,
638 struct sockaddr* name,
639 int* namelen,
640 int delayed_error) {
641
642 int result;
643 uv_os_fd_t fd;
644
645 result = uv_fileno(handle, &fd);
646 if (result != 0)
647 return result;
648
649 if (delayed_error)
650 return uv_translate_sys_error(delayed_error);
651
652 result = func((SOCKET) fd, name, namelen);
653 if (result != 0)
654 return uv_translate_sys_error(WSAGetLastError());
655
656 return 0;
657 }
658