1
0
Эх сурвалжийг харах

libuv 2016-09-27 (8221f9b3)

Code extracted from:

    https://github.com/libuv/libuv.git

at commit 8221f9b305c09205be575d8d34a5c493ba03d392 (v1.x).
libuv upstream 9 жил өмнө
parent
commit
66ac1febc4
4 өөрчлөгдсөн 84 нэмэгдсэн , 41 устгасан
  1. 13 4
      src/unix/fs.c
  2. 5 0
      src/win/fs.c
  3. 57 37
      src/win/tty.c
  4. 9 0
      src/win/util.c

+ 13 - 4
src/unix/fs.c

@@ -346,22 +346,30 @@ done:
 }
 
 
-#if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8))
-static int uv__fs_scandir_filter(uv__dirent_t* dent) {
+#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
+#define UV_CONST_DIRENT uv__dirent_t
 #else
-static int uv__fs_scandir_filter(const uv__dirent_t* dent) {
+#define UV_CONST_DIRENT const uv__dirent_t
 #endif
+
+
+static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
   return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
 }
 
 
+static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
+  return strcmp((*a)->d_name, (*b)->d_name);
+}
+
+
 static ssize_t uv__fs_scandir(uv_fs_t* req) {
   uv__dirent_t **dents;
   int saved_errno;
   int n;
 
   dents = NULL;
-  n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort);
+  n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort);
 
   /* NOTE: We will use nbufs as an index field */
   req->nbufs = 0;
@@ -790,6 +798,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
   dst->st_flags = 0;
   dst->st_gen = 0;
 #elif !defined(_AIX) && (       \
+    defined(_GNU_SOURCE)     || \
     defined(_BSD_SOURCE)     || \
     defined(_SVID_SOURCE)    || \
     defined(_XOPEN_SOURCE)   || \

+ 5 - 0
src/win/fs.c

@@ -230,6 +230,7 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
   req->ptr = NULL;
   req->path = NULL;
   req->cb = cb;
+  memset(&req->fs, 0, sizeof(req->fs));
 }
 
 
@@ -1893,9 +1894,13 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
       uv__free(req->ptr);
   }
 
+  if (req->fs.info.bufs != req->fs.info.bufsml)
+    uv__free(req->fs.info.bufs);
+
   req->path = NULL;
   req->file.pathw = NULL;
   req->fs.info.new_pathw = NULL;
+  req->fs.info.bufs = NULL;
   req->ptr = NULL;
 
   req->flags |= UV_FS_CLEANEDUP;

+ 57 - 37
src/win/tty.c

@@ -111,7 +111,11 @@ static int uv_tty_virtual_offset = -1;
 static int uv_tty_virtual_height = -1;
 static int uv_tty_virtual_width = -1;
 
-static CRITICAL_SECTION uv_tty_output_lock;
+/* We use a semaphore rather than a mutex or critical section because in some
+   cases (uv__cancel_read_console) we need take the lock in the main thread and
+   release it in another thread. Using a semaphore ensures that in such
+   scenario the main thread will still block when trying to acquire the lock. */
+static uv_sem_t uv_tty_output_lock;
 
 static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE;
 
@@ -134,7 +138,8 @@ static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED;
 static void uv__determine_vterm_state(HANDLE handle);
 
 void uv_console_init() {
-  InitializeCriticalSection(&uv_tty_output_lock);
+  if (uv_sem_init(&uv_tty_output_lock, 1))
+    abort();
 }
 
 
@@ -172,7 +177,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
 
     /* Obtain the the tty_output_lock because the virtual window state is */
     /* shared between all uv_tty_t handles. */
-    EnterCriticalSection(&uv_tty_output_lock);
+    uv_sem_wait(&uv_tty_output_lock);
 
     if (uv__vterm_state == UV_UNCHECKED)
       uv__determine_vterm_state(handle);
@@ -187,7 +192,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
 
     uv_tty_update_virtual_window(&screen_buffer_info);
 
-    LeaveCriticalSection(&uv_tty_output_lock);
+    uv_sem_post(&uv_tty_output_lock);
   }
 
 
@@ -315,10 +320,6 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
       return UV_EINVAL;
   }
 
-  if (!SetConsoleMode(tty->handle, flags)) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
   /* If currently reading, stop, and restart reading. */
   if (tty->flags & UV_HANDLE_READING) {
     was_reading = 1;
@@ -332,6 +333,14 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
     was_reading = 0;
   }
 
+  uv_sem_wait(&uv_tty_output_lock);
+  if (!SetConsoleMode(tty->handle, flags)) {
+    err = uv_translate_sys_error(GetLastError());
+    uv_sem_post(&uv_tty_output_lock);
+    return err;
+  }
+  uv_sem_post(&uv_tty_output_lock);
+
   /* Update flag. */
   tty->flags &= ~UV_HANDLE_TTY_RAW;
   tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0;
@@ -361,9 +370,9 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
     return uv_translate_sys_error(GetLastError());
   }
 
-  EnterCriticalSection(&uv_tty_output_lock);
+  uv_sem_wait(&uv_tty_output_lock);
   uv_tty_update_virtual_window(&info);
-  LeaveCriticalSection(&uv_tty_output_lock);
+  uv_sem_post(&uv_tty_output_lock);
 
   *width = uv_tty_virtual_width;
   *height = uv_tty_virtual_height;
@@ -432,6 +441,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
   DWORD chars, read_chars;
   LONG status;
   COORD pos;
+  BOOL read_console_success;
 
   assert(data);
 
@@ -461,11 +471,13 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
     return 0;
   }
 
-  if (ReadConsoleW(handle->handle,
-                   (void*) utf16,
-                   chars,
-                   &read_chars,
-                   NULL)) {
+  read_console_success = ReadConsoleW(handle->handle,
+                                      (void*) utf16,
+                                      chars,
+                                      &read_chars,
+                                      NULL);
+
+  if (read_console_success) {
     read_bytes = WideCharToMultiByte(CP_UTF8,
                                      0,
                                      utf16,
@@ -480,33 +492,36 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
     SET_REQ_ERROR(req, GetLastError());
   }
 
-  InterlockedExchange(&uv__read_console_status, COMPLETED);
+  status = InterlockedExchange(&uv__read_console_status, COMPLETED);
 
-  /* If we canceled the read by sending a VK_RETURN event, restore the screen
-     state to undo the visual effect of the VK_RETURN*/
-  if (InterlockedOr(&uv__restore_screen_state, 0)) {
-    HANDLE active_screen_buffer = CreateFileA("conout$",
+  if (status ==  TRAP_REQUESTED) {
+    /* If we canceled the read by sending a VK_RETURN event, restore the
+       screen state to undo the visual effect of the VK_RETURN */
+    if (read_console_success && InterlockedOr(&uv__restore_screen_state, 0)) {
+      HANDLE active_screen_buffer;
+      active_screen_buffer = CreateFileA("conout$",
                                          GENERIC_READ | GENERIC_WRITE,
                                          FILE_SHARE_READ | FILE_SHARE_WRITE,
                                          NULL,
                                          OPEN_EXISTING,
                                          FILE_ATTRIBUTE_NORMAL,
                                          NULL);
-    if (active_screen_buffer != INVALID_HANDLE_VALUE) {
-      pos = uv__saved_screen_state.dwCursorPosition;
-
-      /* If the cursor was at the bottom line of the screen buffer, the
-         VK_RETURN would have caused the buffer contents to scroll up by
-         one line. The right position to reset the cursor to is therefore one
-         line higher */
-      if (pos.Y == uv__saved_screen_state.dwSize.Y - 1)
-        pos.Y--;
-
-      SetConsoleCursorPosition(active_screen_buffer, pos);
-      CloseHandle(active_screen_buffer);
+      if (active_screen_buffer != INVALID_HANDLE_VALUE) {
+        pos = uv__saved_screen_state.dwCursorPosition;
+
+        /* If the cursor was at the bottom line of the screen buffer, the
+           VK_RETURN would have caused the buffer contents to scroll up by one
+           line. The right position to reset the cursor to is therefore one line
+           higher */
+        if (pos.Y == uv__saved_screen_state.dwSize.Y - 1)
+          pos.Y--;
+
+        SetConsoleCursorPosition(active_screen_buffer, pos);
+        CloseHandle(active_screen_buffer);
+      }
     }
+    uv_sem_post(&uv_tty_output_lock);
   }
-
   POST_COMPLETION_FOR_REQ(loop, req);
   return 0;
 }
@@ -694,14 +709,14 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
       if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
         CONSOLE_SCREEN_BUFFER_INFO info;
 
-        EnterCriticalSection(&uv_tty_output_lock);
+        uv_sem_wait(&uv_tty_output_lock);
 
         if (uv_tty_output_handle != INVALID_HANDLE_VALUE &&
             GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) {
           uv_tty_update_virtual_window(&info);
         }
 
-        LeaveCriticalSection(&uv_tty_output_lock);
+        uv_sem_post(&uv_tty_output_lock);
 
         continue;
       }
@@ -1035,11 +1050,16 @@ static int uv__cancel_read_console(uv_tty_t* handle) {
 
   assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING));
 
+  /* Hold the output lock during the cancellation, to ensure that further
+     writes don't interfere with the screen state. It will be the ReadConsole
+     thread's responsibility to release the lock. */
+  uv_sem_wait(&uv_tty_output_lock);
   status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED);
   if (status != IN_PROGRESS) {
     /* Either we have managed to set a trap for the other thread before
        ReadConsole is called, or ReadConsole has returned because the user
        has pressed ENTER. In either case, there is nothing else to do. */
+    uv_sem_post(&uv_tty_output_lock);
     return 0;
   }
 
@@ -1624,7 +1644,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
   /* state. */
   *error = ERROR_SUCCESS;
 
-  EnterCriticalSection(&uv_tty_output_lock);
+  uv_sem_wait(&uv_tty_output_lock);
 
   for (i = 0; i < nbufs; i++) {
     uv_buf_t buf = bufs[i];
@@ -2061,7 +2081,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
   handle->tty.wr.previous_eol = previous_eol;
   handle->tty.wr.ansi_parser_state = ansi_parser_state;
 
-  LeaveCriticalSection(&uv_tty_output_lock);
+  uv_sem_post(&uv_tty_output_lock);
 
   if (*error == STATUS_SUCCESS) {
     return 0;

+ 9 - 0
src/win/util.c

@@ -1078,6 +1078,7 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
   FILETIME createTime, exitTime, kernelTime, userTime;
   SYSTEMTIME kernelSystemTime, userSystemTime;
   PROCESS_MEMORY_COUNTERS memCounters;
+  IO_COUNTERS ioCounters;
   int ret;
 
   ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
@@ -1102,6 +1103,11 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
     return uv_translate_sys_error(GetLastError());
   }
 
+  ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
+  if (ret == 0) {
+    return uv_translate_sys_error(GetLastError());
+  }
+
   memset(uv_rusage, 0, sizeof(*uv_rusage));
 
   uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
@@ -1117,6 +1123,9 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
   uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
   uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
 
+  uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;
+  uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;
+
   return 0;
 }