libuv 2016-09-27 (8221f9b3)

Code extracted from:

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

at commit 8221f9b305c09205be575d8d34a5c493ba03d392 (v1.x).
This commit is contained in:
libuv upstream 2016-09-27 09:36:57 +02:00 committed by Brad King
parent 3a713eaaf7
commit 66ac1febc4
4 changed files with 82 additions and 39 deletions

View File

@ -346,22 +346,30 @@ done:
} }
#if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)) #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
static int uv__fs_scandir_filter(uv__dirent_t* dent) { #define UV_CONST_DIRENT uv__dirent_t
#else #else
static int uv__fs_scandir_filter(const uv__dirent_t* dent) { #define UV_CONST_DIRENT const uv__dirent_t
#endif #endif
static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; 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) { static ssize_t uv__fs_scandir(uv_fs_t* req) {
uv__dirent_t **dents; uv__dirent_t **dents;
int saved_errno; int saved_errno;
int n; int n;
dents = NULL; 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 */ /* NOTE: We will use nbufs as an index field */
req->nbufs = 0; 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_flags = 0;
dst->st_gen = 0; dst->st_gen = 0;
#elif !defined(_AIX) && ( \ #elif !defined(_AIX) && ( \
defined(_GNU_SOURCE) || \
defined(_BSD_SOURCE) || \ defined(_BSD_SOURCE) || \
defined(_SVID_SOURCE) || \ defined(_SVID_SOURCE) || \
defined(_XOPEN_SOURCE) || \ defined(_XOPEN_SOURCE) || \

View File

@ -230,6 +230,7 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
req->ptr = NULL; req->ptr = NULL;
req->path = NULL; req->path = NULL;
req->cb = cb; 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); uv__free(req->ptr);
} }
if (req->fs.info.bufs != req->fs.info.bufsml)
uv__free(req->fs.info.bufs);
req->path = NULL; req->path = NULL;
req->file.pathw = NULL; req->file.pathw = NULL;
req->fs.info.new_pathw = NULL; req->fs.info.new_pathw = NULL;
req->fs.info.bufs = NULL;
req->ptr = NULL; req->ptr = NULL;
req->flags |= UV_FS_CLEANEDUP; req->flags |= UV_FS_CLEANEDUP;

View File

@ -111,7 +111,11 @@ static int uv_tty_virtual_offset = -1;
static int uv_tty_virtual_height = -1; static int uv_tty_virtual_height = -1;
static int uv_tty_virtual_width = -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; 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); static void uv__determine_vterm_state(HANDLE handle);
void uv_console_init() { 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 */ /* Obtain the the tty_output_lock because the virtual window state is */
/* shared between all uv_tty_t handles. */ /* 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) if (uv__vterm_state == UV_UNCHECKED)
uv__determine_vterm_state(handle); 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); 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; return UV_EINVAL;
} }
if (!SetConsoleMode(tty->handle, flags)) {
return uv_translate_sys_error(GetLastError());
}
/* If currently reading, stop, and restart reading. */ /* If currently reading, stop, and restart reading. */
if (tty->flags & UV_HANDLE_READING) { if (tty->flags & UV_HANDLE_READING) {
was_reading = 1; was_reading = 1;
@ -332,6 +333,14 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
was_reading = 0; 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. */ /* Update flag. */
tty->flags &= ~UV_HANDLE_TTY_RAW; tty->flags &= ~UV_HANDLE_TTY_RAW;
tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0; 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()); return uv_translate_sys_error(GetLastError());
} }
EnterCriticalSection(&uv_tty_output_lock); uv_sem_wait(&uv_tty_output_lock);
uv_tty_update_virtual_window(&info); uv_tty_update_virtual_window(&info);
LeaveCriticalSection(&uv_tty_output_lock); uv_sem_post(&uv_tty_output_lock);
*width = uv_tty_virtual_width; *width = uv_tty_virtual_width;
*height = uv_tty_virtual_height; *height = uv_tty_virtual_height;
@ -432,6 +441,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
DWORD chars, read_chars; DWORD chars, read_chars;
LONG status; LONG status;
COORD pos; COORD pos;
BOOL read_console_success;
assert(data); assert(data);
@ -461,11 +471,13 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
return 0; return 0;
} }
if (ReadConsoleW(handle->handle, read_console_success = ReadConsoleW(handle->handle,
(void*) utf16, (void*) utf16,
chars, chars,
&read_chars, &read_chars,
NULL)) { NULL);
if (read_console_success) {
read_bytes = WideCharToMultiByte(CP_UTF8, read_bytes = WideCharToMultiByte(CP_UTF8,
0, 0,
utf16, utf16,
@ -480,33 +492,36 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
SET_REQ_ERROR(req, GetLastError()); 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 if (status == TRAP_REQUESTED) {
state to undo the visual effect of the VK_RETURN*/ /* If we canceled the read by sending a VK_RETURN event, restore the
if (InterlockedOr(&uv__restore_screen_state, 0)) { screen state to undo the visual effect of the VK_RETURN */
HANDLE active_screen_buffer = CreateFileA("conout$", if (read_console_success && InterlockedOr(&uv__restore_screen_state, 0)) {
HANDLE active_screen_buffer;
active_screen_buffer = CreateFileA("conout$",
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL,
NULL); NULL);
if (active_screen_buffer != INVALID_HANDLE_VALUE) { if (active_screen_buffer != INVALID_HANDLE_VALUE) {
pos = uv__saved_screen_state.dwCursorPosition; pos = uv__saved_screen_state.dwCursorPosition;
/* If the cursor was at the bottom line of the screen buffer, the /* 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 VK_RETURN would have caused the buffer contents to scroll up by one
one line. The right position to reset the cursor to is therefore one line. The right position to reset the cursor to is therefore one line
line higher */ higher */
if (pos.Y == uv__saved_screen_state.dwSize.Y - 1) if (pos.Y == uv__saved_screen_state.dwSize.Y - 1)
pos.Y--; pos.Y--;
SetConsoleCursorPosition(active_screen_buffer, pos); SetConsoleCursorPosition(active_screen_buffer, pos);
CloseHandle(active_screen_buffer); CloseHandle(active_screen_buffer);
}
} }
uv_sem_post(&uv_tty_output_lock);
} }
POST_COMPLETION_FOR_REQ(loop, req); POST_COMPLETION_FOR_REQ(loop, req);
return 0; 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) { if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
CONSOLE_SCREEN_BUFFER_INFO info; 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 && if (uv_tty_output_handle != INVALID_HANDLE_VALUE &&
GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) { GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) {
uv_tty_update_virtual_window(&info); uv_tty_update_virtual_window(&info);
} }
LeaveCriticalSection(&uv_tty_output_lock); uv_sem_post(&uv_tty_output_lock);
continue; continue;
} }
@ -1035,11 +1050,16 @@ static int uv__cancel_read_console(uv_tty_t* handle) {
assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)); 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); status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED);
if (status != IN_PROGRESS) { if (status != IN_PROGRESS) {
/* Either we have managed to set a trap for the other thread before /* Either we have managed to set a trap for the other thread before
ReadConsole is called, or ReadConsole has returned because the user ReadConsole is called, or ReadConsole has returned because the user
has pressed ENTER. In either case, there is nothing else to do. */ has pressed ENTER. In either case, there is nothing else to do. */
uv_sem_post(&uv_tty_output_lock);
return 0; return 0;
} }
@ -1624,7 +1644,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
/* state. */ /* state. */
*error = ERROR_SUCCESS; *error = ERROR_SUCCESS;
EnterCriticalSection(&uv_tty_output_lock); uv_sem_wait(&uv_tty_output_lock);
for (i = 0; i < nbufs; i++) { for (i = 0; i < nbufs; i++) {
uv_buf_t buf = bufs[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.previous_eol = previous_eol;
handle->tty.wr.ansi_parser_state = ansi_parser_state; 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) { if (*error == STATUS_SUCCESS) {
return 0; return 0;

View File

@ -1078,6 +1078,7 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
FILETIME createTime, exitTime, kernelTime, userTime; FILETIME createTime, exitTime, kernelTime, userTime;
SYSTEMTIME kernelSystemTime, userSystemTime; SYSTEMTIME kernelSystemTime, userSystemTime;
PROCESS_MEMORY_COUNTERS memCounters; PROCESS_MEMORY_COUNTERS memCounters;
IO_COUNTERS ioCounters;
int ret; int ret;
ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime); 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()); 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)); memset(uv_rusage, 0, sizeof(*uv_rusage));
uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 + 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_majflt = (uint64_t) memCounters.PageFaultCount;
uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024; 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; return 0;
} }