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