mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-03 12:49:50 -05:00
Merge branch 'upstream-libuv' into update-libuv
* upstream-libuv: libuv 2019-01-15 (f84c5e69)
This commit is contained in:
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com>
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _UV_PTHREAD_BARRIER_
|
|
||||||
#define _UV_PTHREAD_BARRIER_
|
|
||||||
#include <errno.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#if !defined(__MVS__)
|
|
||||||
#include <semaphore.h> /* sem_t */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
|
|
||||||
#define UV__PTHREAD_BARRIER_FALLBACK 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To maintain ABI compatibility with
|
|
||||||
* libuv v1.x struct is padded according
|
|
||||||
* to target platform
|
|
||||||
*/
|
|
||||||
#if defined(__ANDROID__)
|
|
||||||
# define UV_BARRIER_STRUCT_PADDING \
|
|
||||||
sizeof(pthread_mutex_t) + \
|
|
||||||
sizeof(pthread_cond_t) + \
|
|
||||||
sizeof(unsigned int) - \
|
|
||||||
sizeof(void *)
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
# define UV_BARRIER_STRUCT_PADDING \
|
|
||||||
sizeof(pthread_mutex_t) + \
|
|
||||||
2 * sizeof(sem_t) + \
|
|
||||||
2 * sizeof(unsigned int) - \
|
|
||||||
sizeof(void *)
|
|
||||||
#else
|
|
||||||
# define UV_BARRIER_STRUCT_PADDING 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t cond;
|
|
||||||
unsigned threshold;
|
|
||||||
unsigned in;
|
|
||||||
unsigned out;
|
|
||||||
} _uv_barrier;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
_uv_barrier* b;
|
|
||||||
char _pad[UV_BARRIER_STRUCT_PADDING];
|
|
||||||
} pthread_barrier_t;
|
|
||||||
|
|
||||||
int pthread_barrier_init(pthread_barrier_t* barrier,
|
|
||||||
const void* barrier_attr,
|
|
||||||
unsigned count);
|
|
||||||
|
|
||||||
int pthread_barrier_wait(pthread_barrier_t* barrier);
|
|
||||||
int pthread_barrier_destroy(pthread_barrier_t *barrier);
|
|
||||||
|
|
||||||
#endif /* _UV_PTHREAD_BARRIER_ */
|
|
||||||
@@ -49,21 +49,21 @@ extern "C" {
|
|||||||
# define UV_EXTERN /* nothing */
|
# define UV_EXTERN /* nothing */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "uv-errno.h"
|
#include "uv/errno.h"
|
||||||
#include "uv-version.h"
|
#include "uv/version.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||||
# include "stdint-msvc2008.h"
|
# include "uv/stdint-msvc2008.h"
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
# include "uv-win.h"
|
# include "uv/win.h"
|
||||||
#else
|
#else
|
||||||
# include "uv-unix.h"
|
# include "uv/unix.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Expand this list if necessary. */
|
/* Expand this list if necessary. */
|
||||||
@@ -146,6 +146,7 @@ extern "C" {
|
|||||||
XX(EHOSTDOWN, "host is down") \
|
XX(EHOSTDOWN, "host is down") \
|
||||||
XX(EREMOTEIO, "remote I/O error") \
|
XX(EREMOTEIO, "remote I/O error") \
|
||||||
XX(ENOTTY, "inappropriate ioctl for device") \
|
XX(ENOTTY, "inappropriate ioctl for device") \
|
||||||
|
XX(EFTYPE, "inappropriate file type or format") \
|
||||||
|
|
||||||
#define UV_HANDLE_TYPE_MAP(XX) \
|
#define UV_HANDLE_TYPE_MAP(XX) \
|
||||||
XX(ASYNC, async) \
|
XX(ASYNC, async) \
|
||||||
@@ -237,6 +238,7 @@ typedef struct uv_cpu_info_s uv_cpu_info_t;
|
|||||||
typedef struct uv_interface_address_s uv_interface_address_t;
|
typedef struct uv_interface_address_s uv_interface_address_t;
|
||||||
typedef struct uv_dirent_s uv_dirent_t;
|
typedef struct uv_dirent_s uv_dirent_t;
|
||||||
typedef struct uv_passwd_s uv_passwd_t;
|
typedef struct uv_passwd_s uv_passwd_t;
|
||||||
|
typedef struct uv_utsname_s uv_utsname_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UV_LOOP_BLOCK_SIGNAL
|
UV_LOOP_BLOCK_SIGNAL
|
||||||
@@ -373,7 +375,10 @@ typedef enum {
|
|||||||
UV_EXTERN int uv_translate_sys_error(int sys_errno);
|
UV_EXTERN int uv_translate_sys_error(int sys_errno);
|
||||||
|
|
||||||
UV_EXTERN const char* uv_strerror(int err);
|
UV_EXTERN const char* uv_strerror(int err);
|
||||||
|
UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen);
|
||||||
|
|
||||||
UV_EXTERN const char* uv_err_name(int err);
|
UV_EXTERN const char* uv_err_name(int err);
|
||||||
|
UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);
|
||||||
|
|
||||||
|
|
||||||
#define UV_REQ_FIELDS \
|
#define UV_REQ_FIELDS \
|
||||||
@@ -507,7 +512,7 @@ UV_EXTERN int uv_try_write(uv_stream_t* handle,
|
|||||||
struct uv_write_s {
|
struct uv_write_s {
|
||||||
UV_REQ_FIELDS
|
UV_REQ_FIELDS
|
||||||
uv_write_cb cb;
|
uv_write_cb cb;
|
||||||
uv_stream_t* send_handle;
|
uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */
|
||||||
uv_stream_t* handle;
|
uv_stream_t* handle;
|
||||||
UV_WRITE_PRIVATE_FIELDS
|
UV_WRITE_PRIVATE_FIELDS
|
||||||
};
|
};
|
||||||
@@ -869,7 +874,13 @@ typedef enum {
|
|||||||
* flags may be specified to create a duplex data stream.
|
* flags may be specified to create a duplex data stream.
|
||||||
*/
|
*/
|
||||||
UV_READABLE_PIPE = 0x10,
|
UV_READABLE_PIPE = 0x10,
|
||||||
UV_WRITABLE_PIPE = 0x20
|
UV_WRITABLE_PIPE = 0x20,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the child pipe handle in overlapped mode on Windows.
|
||||||
|
* On Unix it is silently ignored.
|
||||||
|
*/
|
||||||
|
UV_OVERLAPPED_PIPE = 0x40
|
||||||
} uv_stdio_flags;
|
} uv_stdio_flags;
|
||||||
|
|
||||||
typedef struct uv_stdio_container_s {
|
typedef struct uv_stdio_container_s {
|
||||||
@@ -969,12 +980,23 @@ enum uv_process_flags {
|
|||||||
* the child's process handle.
|
* the child's process handle.
|
||||||
*/
|
*/
|
||||||
UV_PROCESS_DETACHED = (1 << 3),
|
UV_PROCESS_DETACHED = (1 << 3),
|
||||||
|
/*
|
||||||
|
* Hide the subprocess window that would normally be created. This option is
|
||||||
|
* only meaningful on Windows systems. On Unix it is silently ignored.
|
||||||
|
*/
|
||||||
|
UV_PROCESS_WINDOWS_HIDE = (1 << 4),
|
||||||
/*
|
/*
|
||||||
* Hide the subprocess console window that would normally be created. This
|
* Hide the subprocess console window that would normally be created. This
|
||||||
* option is only meaningful on Windows systems. On Unix it is silently
|
* option is only meaningful on Windows systems. On Unix it is silently
|
||||||
* ignored.
|
* ignored.
|
||||||
*/
|
*/
|
||||||
UV_PROCESS_WINDOWS_HIDE = (1 << 4)
|
UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
|
||||||
|
/*
|
||||||
|
* Hide the subprocess GUI window that would normally be created. This
|
||||||
|
* option is only meaningful on Windows systems. On Unix it is silently
|
||||||
|
* ignored.
|
||||||
|
*/
|
||||||
|
UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1014,16 +1036,18 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop,
|
|||||||
UV_EXTERN int uv_cancel(uv_req_t* req);
|
UV_EXTERN int uv_cancel(uv_req_t* req);
|
||||||
|
|
||||||
|
|
||||||
|
struct uv_cpu_times_s {
|
||||||
|
uint64_t user;
|
||||||
|
uint64_t nice;
|
||||||
|
uint64_t sys;
|
||||||
|
uint64_t idle;
|
||||||
|
uint64_t irq;
|
||||||
|
};
|
||||||
|
|
||||||
struct uv_cpu_info_s {
|
struct uv_cpu_info_s {
|
||||||
char* model;
|
char* model;
|
||||||
int speed;
|
int speed;
|
||||||
struct uv_cpu_times_s {
|
struct uv_cpu_times_s cpu_times;
|
||||||
uint64_t user;
|
|
||||||
uint64_t nice;
|
|
||||||
uint64_t sys;
|
|
||||||
uint64_t idle;
|
|
||||||
uint64_t irq;
|
|
||||||
} cpu_times;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uv_interface_address_s {
|
struct uv_interface_address_s {
|
||||||
@@ -1048,6 +1072,16 @@ struct uv_passwd_s {
|
|||||||
char* homedir;
|
char* homedir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct uv_utsname_s {
|
||||||
|
char sysname[256];
|
||||||
|
char release[256];
|
||||||
|
char version[256];
|
||||||
|
char machine[256];
|
||||||
|
/* This struct does not contain the nodename and domainname fields present in
|
||||||
|
the utsname type. domainname is a GNU extension. Both fields are referred
|
||||||
|
to as meaningless in the docs. */
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UV_DIRENT_UNKNOWN,
|
UV_DIRENT_UNKNOWN,
|
||||||
UV_DIRENT_FILE,
|
UV_DIRENT_FILE,
|
||||||
@@ -1070,6 +1104,7 @@ UV_EXTERN int uv_set_process_title(const char* title);
|
|||||||
UV_EXTERN int uv_resident_set_memory(size_t* rss);
|
UV_EXTERN int uv_resident_set_memory(size_t* rss);
|
||||||
UV_EXTERN int uv_uptime(double* uptime);
|
UV_EXTERN int uv_uptime(double* uptime);
|
||||||
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
|
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
|
||||||
|
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
long tv_sec;
|
long tv_sec;
|
||||||
@@ -1104,6 +1139,16 @@ UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
|
|||||||
UV_EXTERN uv_pid_t uv_os_getpid(void);
|
UV_EXTERN uv_pid_t uv_os_getpid(void);
|
||||||
UV_EXTERN uv_pid_t uv_os_getppid(void);
|
UV_EXTERN uv_pid_t uv_os_getppid(void);
|
||||||
|
|
||||||
|
#define UV_PRIORITY_LOW 19
|
||||||
|
#define UV_PRIORITY_BELOW_NORMAL 10
|
||||||
|
#define UV_PRIORITY_NORMAL 0
|
||||||
|
#define UV_PRIORITY_ABOVE_NORMAL -7
|
||||||
|
#define UV_PRIORITY_HIGH -14
|
||||||
|
#define UV_PRIORITY_HIGHEST -20
|
||||||
|
|
||||||
|
UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
|
||||||
|
UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
|
||||||
|
|
||||||
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
|
||||||
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
|
||||||
UV_EXTERN int uv_cpumask_size(void);
|
UV_EXTERN int uv_cpumask_size(void);
|
||||||
@@ -1119,6 +1164,8 @@ UV_EXTERN int uv_os_unsetenv(const char* name);
|
|||||||
|
|
||||||
UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
|
UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
|
||||||
|
|
||||||
|
UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UV_FS_UNKNOWN = -1,
|
UV_FS_UNKNOWN = -1,
|
||||||
@@ -1151,7 +1198,8 @@ typedef enum {
|
|||||||
UV_FS_CHOWN,
|
UV_FS_CHOWN,
|
||||||
UV_FS_FCHOWN,
|
UV_FS_FCHOWN,
|
||||||
UV_FS_REALPATH,
|
UV_FS_REALPATH,
|
||||||
UV_FS_COPYFILE
|
UV_FS_COPYFILE,
|
||||||
|
UV_FS_LCHOWN
|
||||||
} uv_fs_type;
|
} uv_fs_type;
|
||||||
|
|
||||||
/* uv_fs_t is a subclass of uv_req_t. */
|
/* uv_fs_t is a subclass of uv_req_t. */
|
||||||
@@ -1354,6 +1402,12 @@ UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,
|
|||||||
uv_uid_t uid,
|
uv_uid_t uid,
|
||||||
uv_gid_t gid,
|
uv_gid_t gid,
|
||||||
uv_fs_cb cb);
|
uv_fs_cb cb);
|
||||||
|
UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
|
||||||
|
uv_fs_t* req,
|
||||||
|
const char* path,
|
||||||
|
uv_uid_t uid,
|
||||||
|
uv_gid_t gid,
|
||||||
|
uv_fs_cb cb);
|
||||||
|
|
||||||
|
|
||||||
enum uv_fs_event {
|
enum uv_fs_event {
|
||||||
|
|||||||
@@ -433,5 +433,11 @@
|
|||||||
# define UV__ENOTTY (-4029)
|
# define UV__ENOTTY (-4029)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(EFTYPE) && !defined(_WIN32)
|
||||||
|
# define UV__EFTYPE UV__ERR(EFTYPE)
|
||||||
|
#else
|
||||||
|
# define UV__EFTYPE (-4028)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* UV_ERRNO_H_ */
|
#endif /* UV_ERRNO_H_ */
|
||||||
@@ -42,34 +42,32 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "uv-threadpool.h"
|
#include "uv/threadpool.h"
|
||||||
|
|
||||||
#ifdef CMAKE_BOOTSTRAP
|
#ifdef CMAKE_BOOTSTRAP
|
||||||
# include "uv-posix.h"
|
# include "uv/posix.h"
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
# include "uv-linux.h"
|
# include "uv/linux.h"
|
||||||
#elif defined (__MVS__)
|
#elif defined (__MVS__)
|
||||||
# include "uv-os390.h"
|
# include "uv/os390.h"
|
||||||
#elif defined(__PASE__)
|
#elif defined(__PASE__)
|
||||||
# include "uv-posix.h"
|
# include "uv/posix.h"
|
||||||
#elif defined(_AIX)
|
#elif defined(_AIX)
|
||||||
# include "uv-aix.h"
|
# include "uv/aix.h"
|
||||||
#elif defined(__sun)
|
#elif defined(__sun)
|
||||||
# include "uv-sunos.h"
|
# include "uv/sunos.h"
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
# include "uv-darwin.h"
|
# include "uv/darwin.h"
|
||||||
#elif defined(__DragonFly__) || \
|
#elif defined(__DragonFly__) || \
|
||||||
defined(__FreeBSD__) || \
|
defined(__FreeBSD__) || \
|
||||||
defined(__FreeBSD_kernel__) || \
|
defined(__FreeBSD_kernel__) || \
|
||||||
defined(__OpenBSD__) || \
|
defined(__OpenBSD__) || \
|
||||||
defined(__NetBSD__)
|
defined(__NetBSD__)
|
||||||
# include "uv-bsd.h"
|
# include "uv/bsd.h"
|
||||||
#elif defined(__CYGWIN__) || defined(__MSYS__)
|
#elif defined(__CYGWIN__) || defined(__MSYS__)
|
||||||
# include "uv-posix.h"
|
# include "uv/posix.h"
|
||||||
#endif
|
#elif defined(__GNU__)
|
||||||
|
# include "uv/posix.h"
|
||||||
#ifndef PTHREAD_BARRIER_SERIAL_THREAD
|
|
||||||
# include "pthread-barrier.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NI_MAXHOST
|
#ifndef NI_MAXHOST
|
||||||
@@ -149,9 +147,30 @@ typedef pthread_rwlock_t uv_rwlock_t;
|
|||||||
typedef UV_PLATFORM_SEM_T uv_sem_t;
|
typedef UV_PLATFORM_SEM_T uv_sem_t;
|
||||||
typedef pthread_cond_t uv_cond_t;
|
typedef pthread_cond_t uv_cond_t;
|
||||||
typedef pthread_key_t uv_key_t;
|
typedef pthread_key_t uv_key_t;
|
||||||
|
|
||||||
|
/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
|
||||||
|
#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
/* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
|
||||||
|
struct _uv_barrier {
|
||||||
|
uv_mutex_t mutex;
|
||||||
|
uv_cond_t cond;
|
||||||
|
unsigned threshold;
|
||||||
|
unsigned in;
|
||||||
|
unsigned out;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct _uv_barrier* b;
|
||||||
|
# if defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
/* TODO(bnoordhuis) Remove padding in v2. */
|
||||||
|
char pad[sizeof(pthread_barrier_t) - sizeof(struct _uv_barrier*)];
|
||||||
|
# endif
|
||||||
|
} uv_barrier_t;
|
||||||
|
#else
|
||||||
typedef pthread_barrier_t uv_barrier_t;
|
typedef pthread_barrier_t uv_barrier_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Platform-specific definitions for uv_spawn support. */
|
/* Platform-specific definitions for uv_spawn support. */
|
||||||
typedef gid_t uv_gid_t;
|
typedef gid_t uv_gid_t;
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define UV_VERSION_MAJOR 1
|
#define UV_VERSION_MAJOR 1
|
||||||
#define UV_VERSION_MINOR 20
|
#define UV_VERSION_MINOR 24
|
||||||
#define UV_VERSION_PATCH 3
|
#define UV_VERSION_PATCH 2
|
||||||
#define UV_VERSION_IS_RELEASE 0
|
#define UV_VERSION_IS_RELEASE 0
|
||||||
#define UV_VERSION_SUFFIX "dev"
|
#define UV_VERSION_SUFFIX "dev"
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
|
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
|
||||||
typedef intptr_t ssize_t;
|
typedef intptr_t ssize_t;
|
||||||
|
# define SSIZE_MAX INTPTR_MAX
|
||||||
# define _SSIZE_T_
|
# define _SSIZE_T_
|
||||||
# define _SSIZE_T_DEFINED
|
# define _SSIZE_T_DEFINED
|
||||||
#endif
|
#endif
|
||||||
@@ -53,13 +54,13 @@ typedef struct pollfd {
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||||
# include "stdint-msvc2008.h"
|
# include "uv/stdint-msvc2008.h"
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tree.h"
|
#include "uv/tree.h"
|
||||||
#include "uv-threadpool.h"
|
#include "uv/threadpool.h"
|
||||||
|
|
||||||
#define MAX_PIPENAME_LEN 256
|
#define MAX_PIPENAME_LEN 256
|
||||||
|
|
||||||
@@ -86,8 +87,16 @@ typedef struct pollfd {
|
|||||||
#define SIGKILL 9
|
#define SIGKILL 9
|
||||||
#define SIGWINCH 28
|
#define SIGWINCH 28
|
||||||
|
|
||||||
/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */
|
/* Redefine NSIG to take SIGWINCH into consideration */
|
||||||
/* unix-like platforms. However MinGW doesn't define it, so we do. */
|
#if defined(NSIG) && NSIG <= SIGWINCH
|
||||||
|
# undef NSIG
|
||||||
|
#endif
|
||||||
|
#ifndef NSIG
|
||||||
|
# define NSIG SIGWINCH + 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like
|
||||||
|
* platforms. However MinGW doesn't define it, so we do. */
|
||||||
#ifndef SIGABRT_COMPAT
|
#ifndef SIGABRT_COMPAT
|
||||||
# define SIGABRT_COMPAT 6
|
# define SIGABRT_COMPAT 6
|
||||||
#endif
|
#endif
|
||||||
@@ -255,7 +264,7 @@ typedef union {
|
|||||||
CRITICAL_SECTION waiters_count_lock;
|
CRITICAL_SECTION waiters_count_lock;
|
||||||
HANDLE signal_event;
|
HANDLE signal_event;
|
||||||
HANDLE broadcast_event;
|
HANDLE broadcast_event;
|
||||||
} fallback;
|
} unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
|
||||||
} uv_cond_t;
|
} uv_cond_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@@ -319,8 +328,6 @@ typedef struct {
|
|||||||
char* errmsg;
|
char* errmsg;
|
||||||
} uv_lib_t;
|
} uv_lib_t;
|
||||||
|
|
||||||
RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|
||||||
|
|
||||||
#define UV_LOOP_PRIVATE_FIELDS \
|
#define UV_LOOP_PRIVATE_FIELDS \
|
||||||
/* The loop's I/O completion port */ \
|
/* The loop's I/O completion port */ \
|
||||||
HANDLE iocp; \
|
HANDLE iocp; \
|
||||||
@@ -332,8 +339,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|||||||
uv_req_t* pending_reqs_tail; \
|
uv_req_t* pending_reqs_tail; \
|
||||||
/* Head of a single-linked list of closed handles */ \
|
/* Head of a single-linked list of closed handles */ \
|
||||||
uv_handle_t* endgame_handles; \
|
uv_handle_t* endgame_handles; \
|
||||||
/* The head of the timers tree */ \
|
/* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */ \
|
||||||
struct uv_timer_tree_s timers; \
|
void* timer_heap; \
|
||||||
/* Lists of active loop (prepare / check / idle) watchers */ \
|
/* Lists of active loop (prepare / check / idle) watchers */ \
|
||||||
uv_prepare_t* prepare_handles; \
|
uv_prepare_t* prepare_handles; \
|
||||||
uv_check_t* check_handles; \
|
uv_check_t* check_handles; \
|
||||||
@@ -379,10 +386,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|||||||
} u; \
|
} u; \
|
||||||
struct uv_req_s* next_req;
|
struct uv_req_s* next_req;
|
||||||
|
|
||||||
#define UV_WRITE_PRIVATE_FIELDS \
|
#define UV_WRITE_PRIVATE_FIELDS \
|
||||||
int ipc_header; \
|
int coalesced; \
|
||||||
uv_buf_t write_buffer; \
|
uv_buf_t write_buffer; \
|
||||||
HANDLE event_handle; \
|
HANDLE event_handle; \
|
||||||
HANDLE wait_handle;
|
HANDLE wait_handle;
|
||||||
|
|
||||||
#define UV_CONNECT_PRIVATE_FIELDS \
|
#define UV_CONNECT_PRIVATE_FIELDS \
|
||||||
@@ -470,16 +477,17 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|||||||
|
|
||||||
#define uv_pipe_connection_fields \
|
#define uv_pipe_connection_fields \
|
||||||
uv_timer_t* eof_timer; \
|
uv_timer_t* eof_timer; \
|
||||||
uv_write_t ipc_header_write_req; \
|
uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||||
int ipc_pid; \
|
DWORD ipc_remote_pid; \
|
||||||
uint64_t remaining_ipc_rawdata_bytes; \
|
union { \
|
||||||
struct { \
|
uint32_t payload_remaining; \
|
||||||
void* queue[2]; \
|
uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
|
||||||
int queue_len; \
|
} ipc_data_frame; \
|
||||||
} pending_ipc_info; \
|
void* ipc_xfer_queue[2]; \
|
||||||
|
int ipc_xfer_queue_length; \
|
||||||
uv_write_t* non_overlapped_writes_tail; \
|
uv_write_t* non_overlapped_writes_tail; \
|
||||||
uv_mutex_t readfile_mutex; \
|
CRITICAL_SECTION readfile_thread_lock; \
|
||||||
volatile HANDLE readfile_thread;
|
volatile HANDLE readfile_thread_handle;
|
||||||
|
|
||||||
#define UV_PIPE_PRIVATE_FIELDS \
|
#define UV_PIPE_PRIVATE_FIELDS \
|
||||||
HANDLE handle; \
|
HANDLE handle; \
|
||||||
@@ -489,8 +497,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|||||||
struct { uv_pipe_connection_fields } conn; \
|
struct { uv_pipe_connection_fields } conn; \
|
||||||
} pipe;
|
} pipe;
|
||||||
|
|
||||||
/* TODO: put the parser states in an union - TTY handles are always */
|
/* TODO: put the parser states in an union - TTY handles are always half-duplex
|
||||||
/* half-duplex so read-state can safely overlap write-state. */
|
* so read-state can safely overlap write-state. */
|
||||||
#define UV_TTY_PRIVATE_FIELDS \
|
#define UV_TTY_PRIVATE_FIELDS \
|
||||||
HANDLE handle; \
|
HANDLE handle; \
|
||||||
union { \
|
union { \
|
||||||
@@ -539,8 +547,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
|||||||
unsigned char events;
|
unsigned char events;
|
||||||
|
|
||||||
#define UV_TIMER_PRIVATE_FIELDS \
|
#define UV_TIMER_PRIVATE_FIELDS \
|
||||||
RB_ENTRY(uv_timer_s) tree_entry; \
|
void* heap_node[3]; \
|
||||||
uint64_t due; \
|
int unused; \
|
||||||
|
uint64_t timeout; \
|
||||||
uint64_t repeat; \
|
uint64_t repeat; \
|
||||||
uint64_t start_id; \
|
uint64_t start_id; \
|
||||||
uv_timer_cb timer_cb;
|
uv_timer_cb timer_cb;
|
||||||
@@ -83,7 +83,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ctx->timer_handle.flags |= UV__HANDLE_INTERNAL;
|
ctx->timer_handle.flags |= UV_HANDLE_INTERNAL;
|
||||||
uv__handle_unref(&ctx->timer_handle);
|
uv__handle_unref(&ctx->timer_handle);
|
||||||
|
|
||||||
err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);
|
err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);
|
||||||
@@ -248,7 +248,7 @@ static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) {
|
|||||||
#include "win/handle-inl.h"
|
#include "win/handle-inl.h"
|
||||||
|
|
||||||
void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
|
void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
|
||||||
assert(handle->flags & UV__HANDLE_CLOSING);
|
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
uv__handle_close(handle);
|
uv__handle_close(handle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,291 @@
|
|||||||
|
/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Derived from https://github.com/bnoordhuis/punycode
|
||||||
|
* but updated to support IDNA 2008.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "idna.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static unsigned uv__utf8_decode1_slow(const char** p,
|
||||||
|
const char* pe,
|
||||||
|
unsigned a) {
|
||||||
|
unsigned b;
|
||||||
|
unsigned c;
|
||||||
|
unsigned d;
|
||||||
|
unsigned min;
|
||||||
|
|
||||||
|
if (a > 0xF7)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (*p - pe) {
|
||||||
|
default:
|
||||||
|
if (a > 0xEF) {
|
||||||
|
min = 0x10000;
|
||||||
|
a = a & 7;
|
||||||
|
b = (unsigned char) *(*p)++;
|
||||||
|
c = (unsigned char) *(*p)++;
|
||||||
|
d = (unsigned char) *(*p)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through. */
|
||||||
|
case 2:
|
||||||
|
if (a > 0xDF) {
|
||||||
|
min = 0x800;
|
||||||
|
b = 0x80 | (a & 15);
|
||||||
|
c = (unsigned char) *(*p)++;
|
||||||
|
d = (unsigned char) *(*p)++;
|
||||||
|
a = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through. */
|
||||||
|
case 1:
|
||||||
|
if (a > 0xBF) {
|
||||||
|
min = 0x80;
|
||||||
|
b = 0x80;
|
||||||
|
c = 0x80 | (a & 31);
|
||||||
|
d = (unsigned char) *(*p)++;
|
||||||
|
a = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -1; /* Invalid continuation byte. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0x80 != (0xC0 & (b ^ c ^ d)))
|
||||||
|
return -1; /* Invalid sequence. */
|
||||||
|
|
||||||
|
b &= 63;
|
||||||
|
c &= 63;
|
||||||
|
d &= 63;
|
||||||
|
a = (a << 18) | (b << 12) | (c << 6) | d;
|
||||||
|
|
||||||
|
if (a < min)
|
||||||
|
return -1; /* Overlong sequence. */
|
||||||
|
|
||||||
|
if (a > 0x10FFFF)
|
||||||
|
return -1; /* Four-byte sequence > U+10FFFF. */
|
||||||
|
|
||||||
|
if (a >= 0xD800 && a <= 0xDFFF)
|
||||||
|
return -1; /* Surrogate pair. */
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned uv__utf8_decode1(const char** p, const char* pe) {
|
||||||
|
unsigned a;
|
||||||
|
|
||||||
|
a = (unsigned char) *(*p)++;
|
||||||
|
|
||||||
|
if (a < 128)
|
||||||
|
return a; /* ASCII, common case. */
|
||||||
|
|
||||||
|
return uv__utf8_decode1_slow(p, pe, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define foreach_codepoint(c, p, pe) \
|
||||||
|
for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)
|
||||||
|
|
||||||
|
static int uv__idna_toascii_label(const char* s, const char* se,
|
||||||
|
char** d, char* de) {
|
||||||
|
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
const char* ss;
|
||||||
|
unsigned c;
|
||||||
|
unsigned h;
|
||||||
|
unsigned k;
|
||||||
|
unsigned n;
|
||||||
|
unsigned m;
|
||||||
|
unsigned q;
|
||||||
|
unsigned t;
|
||||||
|
unsigned x;
|
||||||
|
unsigned y;
|
||||||
|
unsigned bias;
|
||||||
|
unsigned delta;
|
||||||
|
unsigned todo;
|
||||||
|
int first;
|
||||||
|
|
||||||
|
h = 0;
|
||||||
|
ss = s;
|
||||||
|
todo = 0;
|
||||||
|
|
||||||
|
foreach_codepoint(c, &s, se) {
|
||||||
|
if (c < 128)
|
||||||
|
h++;
|
||||||
|
else if (c == (unsigned) -1)
|
||||||
|
return UV_EINVAL;
|
||||||
|
else
|
||||||
|
todo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (todo > 0) {
|
||||||
|
if (*d < de) *(*d)++ = 'x';
|
||||||
|
if (*d < de) *(*d)++ = 'n';
|
||||||
|
if (*d < de) *(*d)++ = '-';
|
||||||
|
if (*d < de) *(*d)++ = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
s = ss;
|
||||||
|
foreach_codepoint(c, &s, se) {
|
||||||
|
if (c > 127)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (*d < de)
|
||||||
|
*(*d)++ = c;
|
||||||
|
|
||||||
|
if (++x == h)
|
||||||
|
break; /* Visited all ASCII characters. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (todo == 0)
|
||||||
|
return h;
|
||||||
|
|
||||||
|
/* Only write separator when we've written ASCII characters first. */
|
||||||
|
if (h > 0)
|
||||||
|
if (*d < de)
|
||||||
|
*(*d)++ = '-';
|
||||||
|
|
||||||
|
n = 128;
|
||||||
|
bias = 72;
|
||||||
|
delta = 0;
|
||||||
|
first = 1;
|
||||||
|
|
||||||
|
while (todo > 0) {
|
||||||
|
m = -1;
|
||||||
|
s = ss;
|
||||||
|
foreach_codepoint(c, &s, se)
|
||||||
|
if (c >= n)
|
||||||
|
if (c < m)
|
||||||
|
m = c;
|
||||||
|
|
||||||
|
x = m - n;
|
||||||
|
y = h + 1;
|
||||||
|
|
||||||
|
if (x > ~delta / y)
|
||||||
|
return UV_E2BIG; /* Overflow. */
|
||||||
|
|
||||||
|
delta += x * y;
|
||||||
|
n = m;
|
||||||
|
|
||||||
|
s = ss;
|
||||||
|
foreach_codepoint(c, &s, se) {
|
||||||
|
if (c < n)
|
||||||
|
if (++delta == 0)
|
||||||
|
return UV_E2BIG; /* Overflow. */
|
||||||
|
|
||||||
|
if (c != n)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (k = 36, q = delta; /* empty */; k += 36) {
|
||||||
|
t = 1;
|
||||||
|
|
||||||
|
if (k > bias)
|
||||||
|
t = k - bias;
|
||||||
|
|
||||||
|
if (t > 26)
|
||||||
|
t = 26;
|
||||||
|
|
||||||
|
if (q < t)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* TODO(bnoordhuis) Since 1 <= t <= 26 and therefore
|
||||||
|
* 10 <= y <= 35, we can optimize the long division
|
||||||
|
* into a table-based reciprocal multiplication.
|
||||||
|
*/
|
||||||
|
x = q - t;
|
||||||
|
y = 36 - t; /* 10 <= y <= 35 since 1 <= t <= 26. */
|
||||||
|
q = x / y;
|
||||||
|
t = t + x % y; /* 1 <= t <= 35 because of y. */
|
||||||
|
|
||||||
|
if (*d < de)
|
||||||
|
*(*d)++ = alphabet[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*d < de)
|
||||||
|
*(*d)++ = alphabet[q];
|
||||||
|
|
||||||
|
delta /= 2;
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
delta /= 350;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No overflow check is needed because |delta| was just
|
||||||
|
* divided by 2 and |delta+delta >= delta + delta/h|.
|
||||||
|
*/
|
||||||
|
h++;
|
||||||
|
delta += delta / h;
|
||||||
|
|
||||||
|
for (bias = 0; delta > 35 * 26 / 2; bias += 36)
|
||||||
|
delta /= 35;
|
||||||
|
|
||||||
|
bias += 36 * delta / (delta + 38);
|
||||||
|
delta = 0;
|
||||||
|
todo--;
|
||||||
|
}
|
||||||
|
|
||||||
|
delta++;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef foreach_codepoint
|
||||||
|
|
||||||
|
long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
|
||||||
|
const char* si;
|
||||||
|
const char* st;
|
||||||
|
unsigned c;
|
||||||
|
char* ds;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
ds = d;
|
||||||
|
|
||||||
|
for (si = s; si < se; /* empty */) {
|
||||||
|
st = si;
|
||||||
|
c = uv__utf8_decode1(&si, se);
|
||||||
|
|
||||||
|
if (c != '.')
|
||||||
|
if (c != 0x3002) /* 。 */
|
||||||
|
if (c != 0xFF0E) /* . */
|
||||||
|
if (c != 0xFF61) /* 。 */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rc = uv__idna_toascii_label(s, st, &d, de);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (d < de)
|
||||||
|
*d++ = '.';
|
||||||
|
|
||||||
|
s = si;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s < se) {
|
||||||
|
rc = uv__idna_toascii_label(s, se, &d, de);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d < de)
|
||||||
|
*d++ = '\0';
|
||||||
|
|
||||||
|
return d - ds; /* Number of bytes written. */
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UV_SRC_IDNA_H_
|
||||||
|
#define UV_SRC_IDNA_H_
|
||||||
|
|
||||||
|
/* Decode a single codepoint. Returns the codepoint or UINT32_MAX on error.
|
||||||
|
* |p| is updated on success _and_ error, i.e., bad multi-byte sequences are
|
||||||
|
* skipped in their entirety, not just the first bad byte.
|
||||||
|
*/
|
||||||
|
unsigned uv__utf8_decode1(const char** p, const char* pe);
|
||||||
|
|
||||||
|
/* Convert a UTF-8 domain name to IDNA 2008 / Punycode. A return value >= 0
|
||||||
|
* is the number of bytes written to |d|, including the trailing nul byte.
|
||||||
|
* A return value < 0 is a libuv error code. |s| and |d| can not overlap.
|
||||||
|
*/
|
||||||
|
long uv__idna_toascii(const char* s, const char* se, char* d, char* de);
|
||||||
|
|
||||||
|
#endif /* UV_SRC_IDNA_H_ */
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||||
# include "stdint-msvc2008.h"
|
# include "uv/stdint-msvc2008.h"
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -59,8 +59,7 @@ static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {
|
|||||||
if (l <= 0 || (size_t) l >= size) {
|
if (l <= 0 || (size_t) l >= size) {
|
||||||
return UV_ENOSPC;
|
return UV_ENOSPC;
|
||||||
}
|
}
|
||||||
strncpy(dst, tmp, size);
|
uv__strscpy(dst, tmp, size);
|
||||||
dst[size - 1] = '\0';
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,14 +141,8 @@ static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
|
|||||||
if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
|
if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
|
||||||
*tp++ = ':';
|
*tp++ = ':';
|
||||||
*tp++ = '\0';
|
*tp++ = '\0';
|
||||||
|
if (UV_E2BIG == uv__strscpy(dst, tmp, size))
|
||||||
/*
|
|
||||||
* Check for overflow, copy, and we're done.
|
|
||||||
*/
|
|
||||||
if ((size_t)(tp - tmp) > size) {
|
|
||||||
return UV_ENOSPC;
|
return UV_ENOSPC;
|
||||||
}
|
|
||||||
strcpy(dst, tmp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#include "strscpy.h"
|
||||||
|
#include <limits.h> /* SSIZE_MAX */
|
||||||
|
|
||||||
|
ssize_t uv__strscpy(char* d, const char* s, size_t n) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if ('\0' == (d[i] = s[i]))
|
||||||
|
return i > SSIZE_MAX ? UV_E2BIG : (ssize_t) i;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
d[--i] = '\0';
|
||||||
|
|
||||||
|
return UV_E2BIG;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef UV_STRSCPY_H_
|
||||||
|
#define UV_STRSCPY_H_
|
||||||
|
|
||||||
|
/* Include uv.h for its definitions of size_t and ssize_t.
|
||||||
|
* size_t can be obtained directly from <stddef.h> but ssize_t requires
|
||||||
|
* some hoop jumping on Windows that I didn't want to duplicate here.
|
||||||
|
*/
|
||||||
|
#include "uv.h"
|
||||||
|
|
||||||
|
/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates
|
||||||
|
* the result, except when |n==0|. Returns the number of bytes copied
|
||||||
|
* or UV_E2BIG if |d| is too small.
|
||||||
|
*
|
||||||
|
* See https://www.kernel.org/doc/htmldocs/kernel-api/API-strscpy.html
|
||||||
|
*/
|
||||||
|
ssize_t uv__strscpy(char* d, const char* s, size_t n);
|
||||||
|
|
||||||
|
#endif /* UV_STRSCPY_H_ */
|
||||||
@@ -33,12 +33,18 @@ static uv_once_t once = UV_ONCE_INIT;
|
|||||||
static uv_cond_t cond;
|
static uv_cond_t cond;
|
||||||
static uv_mutex_t mutex;
|
static uv_mutex_t mutex;
|
||||||
static unsigned int idle_threads;
|
static unsigned int idle_threads;
|
||||||
|
static unsigned int slow_io_work_running;
|
||||||
static unsigned int nthreads;
|
static unsigned int nthreads;
|
||||||
static uv_thread_t* threads;
|
static uv_thread_t* threads;
|
||||||
static uv_thread_t default_threads[4];
|
static uv_thread_t default_threads[4];
|
||||||
static QUEUE exit_message;
|
static QUEUE exit_message;
|
||||||
static QUEUE wq;
|
static QUEUE wq;
|
||||||
|
static QUEUE run_slow_work_message;
|
||||||
|
static QUEUE slow_io_pending_wq;
|
||||||
|
|
||||||
|
static unsigned int slow_work_thread_threshold(void) {
|
||||||
|
return (nthreads + 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
static void uv__cancelled(struct uv__work* w) {
|
static void uv__cancelled(struct uv__work* w) {
|
||||||
abort();
|
abort();
|
||||||
@@ -51,34 +57,67 @@ static void uv__cancelled(struct uv__work* w) {
|
|||||||
static void worker(void* arg) {
|
static void worker(void* arg) {
|
||||||
struct uv__work* w;
|
struct uv__work* w;
|
||||||
QUEUE* q;
|
QUEUE* q;
|
||||||
|
int is_slow_work;
|
||||||
|
|
||||||
uv_sem_post((uv_sem_t*) arg);
|
uv_sem_post((uv_sem_t*) arg);
|
||||||
arg = NULL;
|
arg = NULL;
|
||||||
|
|
||||||
|
uv_mutex_lock(&mutex);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uv_mutex_lock(&mutex);
|
/* `mutex` should always be locked at this point. */
|
||||||
|
|
||||||
while (QUEUE_EMPTY(&wq)) {
|
/* Keep waiting while either no work is present or only slow I/O
|
||||||
|
and we're at the threshold for that. */
|
||||||
|
while (QUEUE_EMPTY(&wq) ||
|
||||||
|
(QUEUE_HEAD(&wq) == &run_slow_work_message &&
|
||||||
|
QUEUE_NEXT(&run_slow_work_message) == &wq &&
|
||||||
|
slow_io_work_running >= slow_work_thread_threshold())) {
|
||||||
idle_threads += 1;
|
idle_threads += 1;
|
||||||
uv_cond_wait(&cond, &mutex);
|
uv_cond_wait(&cond, &mutex);
|
||||||
idle_threads -= 1;
|
idle_threads -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
q = QUEUE_HEAD(&wq);
|
q = QUEUE_HEAD(&wq);
|
||||||
|
if (q == &exit_message) {
|
||||||
if (q == &exit_message)
|
|
||||||
uv_cond_signal(&cond);
|
uv_cond_signal(&cond);
|
||||||
else {
|
uv_mutex_unlock(&mutex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUEUE_REMOVE(q);
|
||||||
|
QUEUE_INIT(q); /* Signal uv_cancel() that the work req is executing. */
|
||||||
|
|
||||||
|
is_slow_work = 0;
|
||||||
|
if (q == &run_slow_work_message) {
|
||||||
|
/* If we're at the slow I/O threshold, re-schedule until after all
|
||||||
|
other work in the queue is done. */
|
||||||
|
if (slow_io_work_running >= slow_work_thread_threshold()) {
|
||||||
|
QUEUE_INSERT_TAIL(&wq, q);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we encountered a request to run slow I/O work but there is none
|
||||||
|
to run, that means it's cancelled => Start over. */
|
||||||
|
if (QUEUE_EMPTY(&slow_io_pending_wq))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
is_slow_work = 1;
|
||||||
|
slow_io_work_running++;
|
||||||
|
|
||||||
|
q = QUEUE_HEAD(&slow_io_pending_wq);
|
||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
QUEUE_INIT(q); /* Signal uv_cancel() that the work req is
|
QUEUE_INIT(q);
|
||||||
executing. */
|
|
||||||
|
/* If there is more slow I/O work, schedule it to be run as well. */
|
||||||
|
if (!QUEUE_EMPTY(&slow_io_pending_wq)) {
|
||||||
|
QUEUE_INSERT_TAIL(&wq, &run_slow_work_message);
|
||||||
|
if (idle_threads > 0)
|
||||||
|
uv_cond_signal(&cond);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_mutex_unlock(&mutex);
|
uv_mutex_unlock(&mutex);
|
||||||
|
|
||||||
if (q == &exit_message)
|
|
||||||
break;
|
|
||||||
|
|
||||||
w = QUEUE_DATA(q, struct uv__work, wq);
|
w = QUEUE_DATA(q, struct uv__work, wq);
|
||||||
w->work(w);
|
w->work(w);
|
||||||
|
|
||||||
@@ -88,12 +127,32 @@ static void worker(void* arg) {
|
|||||||
QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
|
QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
|
||||||
uv_async_send(&w->loop->wq_async);
|
uv_async_send(&w->loop->wq_async);
|
||||||
uv_mutex_unlock(&w->loop->wq_mutex);
|
uv_mutex_unlock(&w->loop->wq_mutex);
|
||||||
|
|
||||||
|
/* Lock `mutex` since that is expected at the start of the next
|
||||||
|
* iteration. */
|
||||||
|
uv_mutex_lock(&mutex);
|
||||||
|
if (is_slow_work) {
|
||||||
|
/* `slow_io_work_running` is protected by `mutex`. */
|
||||||
|
slow_io_work_running--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void post(QUEUE* q) {
|
static void post(QUEUE* q, enum uv__work_kind kind) {
|
||||||
uv_mutex_lock(&mutex);
|
uv_mutex_lock(&mutex);
|
||||||
|
if (kind == UV__WORK_SLOW_IO) {
|
||||||
|
/* Insert into a separate queue. */
|
||||||
|
QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);
|
||||||
|
if (!QUEUE_EMPTY(&run_slow_work_message)) {
|
||||||
|
/* Running slow I/O tasks is already scheduled => Nothing to do here.
|
||||||
|
The worker that runs said other task will schedule this one as well. */
|
||||||
|
uv_mutex_unlock(&mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
q = &run_slow_work_message;
|
||||||
|
}
|
||||||
|
|
||||||
QUEUE_INSERT_TAIL(&wq, q);
|
QUEUE_INSERT_TAIL(&wq, q);
|
||||||
if (idle_threads > 0)
|
if (idle_threads > 0)
|
||||||
uv_cond_signal(&cond);
|
uv_cond_signal(&cond);
|
||||||
@@ -108,7 +167,7 @@ UV_DESTRUCTOR(static void cleanup(void)) {
|
|||||||
if (nthreads == 0)
|
if (nthreads == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
post(&exit_message);
|
post(&exit_message, UV__WORK_CPU);
|
||||||
|
|
||||||
for (i = 0; i < nthreads; i++)
|
for (i = 0; i < nthreads; i++)
|
||||||
if (uv_thread_join(threads + i))
|
if (uv_thread_join(threads + i))
|
||||||
@@ -156,6 +215,8 @@ static void init_threads(void) {
|
|||||||
abort();
|
abort();
|
||||||
|
|
||||||
QUEUE_INIT(&wq);
|
QUEUE_INIT(&wq);
|
||||||
|
QUEUE_INIT(&slow_io_pending_wq);
|
||||||
|
QUEUE_INIT(&run_slow_work_message);
|
||||||
|
|
||||||
if (uv_sem_init(&sem, 0))
|
if (uv_sem_init(&sem, 0))
|
||||||
abort();
|
abort();
|
||||||
@@ -194,13 +255,14 @@ static void init_once(void) {
|
|||||||
|
|
||||||
void uv__work_submit(uv_loop_t* loop,
|
void uv__work_submit(uv_loop_t* loop,
|
||||||
struct uv__work* w,
|
struct uv__work* w,
|
||||||
|
enum uv__work_kind kind,
|
||||||
void (*work)(struct uv__work* w),
|
void (*work)(struct uv__work* w),
|
||||||
void (*done)(struct uv__work* w, int status)) {
|
void (*done)(struct uv__work* w, int status)) {
|
||||||
uv_once(&once, init_once);
|
uv_once(&once, init_once);
|
||||||
w->loop = loop;
|
w->loop = loop;
|
||||||
w->work = work;
|
w->work = work;
|
||||||
w->done = done;
|
w->done = done;
|
||||||
post(&w->wq);
|
post(&w->wq, kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -284,7 +346,11 @@ int uv_queue_work(uv_loop_t* loop,
|
|||||||
req->loop = loop;
|
req->loop = loop;
|
||||||
req->work_cb = work_cb;
|
req->work_cb = work_cb;
|
||||||
req->after_work_cb = after_work_cb;
|
req->after_work_cb = after_work_cb;
|
||||||
uv__work_submit(loop, &req->work_req, uv__queue_work, uv__queue_done);
|
uv__work_submit(loop,
|
||||||
|
&req->work_req,
|
||||||
|
UV__WORK_CPU,
|
||||||
|
uv__queue_work,
|
||||||
|
uv__queue_done);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "internal.h"
|
#include "uv-common.h"
|
||||||
#include "heap-inl.h"
|
#include "heap-inl.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
static struct heap *timer_heap(const uv_loop_t* loop) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return (struct heap*) loop->timer_heap;
|
||||||
|
#else
|
||||||
|
return (struct heap*) &loop->timer_heap;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int timer_less_than(const struct heap_node* ha,
|
static int timer_less_than(const struct heap_node* ha,
|
||||||
const struct heap_node* hb) {
|
const struct heap_node* hb) {
|
||||||
const uv_timer_t* a;
|
const uv_timer_t* a;
|
||||||
@@ -81,7 +90,7 @@ int uv_timer_start(uv_timer_t* handle,
|
|||||||
/* start_id is the second index to be compared in uv__timer_cmp() */
|
/* start_id is the second index to be compared in uv__timer_cmp() */
|
||||||
handle->start_id = handle->loop->timer_counter++;
|
handle->start_id = handle->loop->timer_counter++;
|
||||||
|
|
||||||
heap_insert((struct heap*) &handle->loop->timer_heap,
|
heap_insert(timer_heap(handle->loop),
|
||||||
(struct heap_node*) &handle->heap_node,
|
(struct heap_node*) &handle->heap_node,
|
||||||
timer_less_than);
|
timer_less_than);
|
||||||
uv__handle_start(handle);
|
uv__handle_start(handle);
|
||||||
@@ -94,7 +103,7 @@ int uv_timer_stop(uv_timer_t* handle) {
|
|||||||
if (!uv__is_active(handle))
|
if (!uv__is_active(handle))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
heap_remove((struct heap*) &handle->loop->timer_heap,
|
heap_remove(timer_heap(handle->loop),
|
||||||
(struct heap_node*) &handle->heap_node,
|
(struct heap_node*) &handle->heap_node,
|
||||||
timer_less_than);
|
timer_less_than);
|
||||||
uv__handle_stop(handle);
|
uv__handle_stop(handle);
|
||||||
@@ -131,7 +140,7 @@ int uv__next_timeout(const uv_loop_t* loop) {
|
|||||||
const uv_timer_t* handle;
|
const uv_timer_t* handle;
|
||||||
uint64_t diff;
|
uint64_t diff;
|
||||||
|
|
||||||
heap_node = heap_min((const struct heap*) &loop->timer_heap);
|
heap_node = heap_min(timer_heap(loop));
|
||||||
if (heap_node == NULL)
|
if (heap_node == NULL)
|
||||||
return -1; /* block indefinitely */
|
return -1; /* block indefinitely */
|
||||||
|
|
||||||
@@ -143,7 +152,7 @@ int uv__next_timeout(const uv_loop_t* loop) {
|
|||||||
if (diff > INT_MAX)
|
if (diff > INT_MAX)
|
||||||
diff = INT_MAX;
|
diff = INT_MAX;
|
||||||
|
|
||||||
return diff;
|
return (int) diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -152,7 +161,7 @@ void uv__run_timers(uv_loop_t* loop) {
|
|||||||
uv_timer_t* handle;
|
uv_timer_t* handle;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
heap_node = heap_min((struct heap*) &loop->timer_heap);
|
heap_node = heap_min(timer_heap(loop));
|
||||||
if (heap_node == NULL)
|
if (heap_node == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -166,8 +166,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_interface_addresses(uv_interface_address_t** addresses,
|
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||||
int* count) {
|
|
||||||
uv_interface_address_t* address;
|
uv_interface_address_t* address;
|
||||||
int sockfd, inet6, size = 1;
|
int sockfd, inet6, size = 1;
|
||||||
struct ifconf ifc;
|
struct ifconf ifc;
|
||||||
@@ -175,6 +174,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
|||||||
struct sockaddr_dl* sa_addr;
|
struct sockaddr_dl* sa_addr;
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
*addresses = NULL;
|
||||||
|
|
||||||
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
|
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
|
||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
@@ -217,6 +217,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
|||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*count == 0) {
|
||||||
|
uv__close(sockfd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Alloc the return interface structs */
|
/* Alloc the return interface structs */
|
||||||
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
|
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
|
||||||
if (!(*addresses)) {
|
if (!(*addresses)) {
|
||||||
@@ -290,3 +295,4 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
|||||||
|
|
||||||
uv__free(addresses);
|
uv__free(addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -358,19 +358,15 @@ void uv_loadavg(double avg[3]) {
|
|||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
|
#ifdef HAVE_SYS_AHAFS_EVPRODS_H
|
||||||
static char *uv__rawname(char *cp) {
|
static char* uv__rawname(const char* cp, char (*dst)[FILENAME_MAX+1]) {
|
||||||
static char rawbuf[FILENAME_MAX+1];
|
char* dp;
|
||||||
char *dp = rindex(cp, '/');
|
|
||||||
|
|
||||||
|
dp = rindex(cp, '/');
|
||||||
if (dp == 0)
|
if (dp == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*dp = 0;
|
snprintf(*dst, sizeof(*dst), "%.*s/r%s", (int) (dp - cp), cp, dp + 1);
|
||||||
strcpy(rawbuf, cp);
|
return *dst;
|
||||||
*dp = '/';
|
|
||||||
strcat(rawbuf, "/r");
|
|
||||||
strcat(rawbuf, dp+1);
|
|
||||||
return rawbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -399,6 +395,7 @@ static int uv__path_is_a_directory(char* filename) {
|
|||||||
* Returns 0 if AHAFS is mounted, or an error code < 0 on failure
|
* Returns 0 if AHAFS is mounted, or an error code < 0 on failure
|
||||||
*/
|
*/
|
||||||
static int uv__is_ahafs_mounted(void){
|
static int uv__is_ahafs_mounted(void){
|
||||||
|
char rawbuf[FILENAME_MAX+1];
|
||||||
int rv, i = 2;
|
int rv, i = 2;
|
||||||
struct vmount *p;
|
struct vmount *p;
|
||||||
int size_multiplier = 10;
|
int size_multiplier = 10;
|
||||||
@@ -432,7 +429,7 @@ static int uv__is_ahafs_mounted(void){
|
|||||||
obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */
|
obj = vmt2dataptr(vmt, VMT_OBJECT); /* device */
|
||||||
stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */
|
stub = vmt2dataptr(vmt, VMT_STUB); /* mount point */
|
||||||
|
|
||||||
if (EQ(obj, dev) || EQ(uv__rawname(obj), dev) || EQ(stub, dev)) {
|
if (EQ(obj, dev) || EQ(uv__rawname(obj, &rawbuf), dev) || EQ(stub, dev)) {
|
||||||
uv__free(p); /* Found a match */
|
uv__free(p); /* Found a match */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -453,7 +450,8 @@ static int uv__makedir_p(const char *dir) {
|
|||||||
size_t len;
|
size_t len;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
snprintf(tmp, sizeof(tmp),"%s",dir);
|
/* TODO(bnoordhuis) Check uv__strscpy() return value. */
|
||||||
|
uv__strscpy(tmp, dir, sizeof(tmp));
|
||||||
len = strlen(tmp);
|
len = strlen(tmp);
|
||||||
if (tmp[len - 1] == '/')
|
if (tmp[len - 1] == '/')
|
||||||
tmp[len - 1] = 0;
|
tmp[len - 1] = 0;
|
||||||
@@ -557,7 +555,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
|
|||||||
sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1");
|
sprintf(mon_file_write_string, "CHANGED=YES;WAIT_TYPE=WAIT_IN_SELECT;INFO_LVL=1");
|
||||||
|
|
||||||
rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
|
rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
|
||||||
if (rc < 0)
|
if (rc < 0 && errno != EBUSY)
|
||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -702,9 +700,9 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int
|
|||||||
else
|
else
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
strncpy(fname, p, sizeof(fname) - 1);
|
|
||||||
/* Just in case */
|
/* TODO(bnoordhuis) Check uv__strscpy() return value. */
|
||||||
fname[sizeof(fname) - 1] = '\0';
|
uv__strscpy(fname, p, sizeof(fname));
|
||||||
|
|
||||||
handle->cb(handle, fname, events, 0);
|
handle->cb(handle, fname, events, 0);
|
||||||
}
|
}
|
||||||
@@ -730,12 +728,19 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
char absolute_path[PATH_MAX];
|
char absolute_path[PATH_MAX];
|
||||||
char readlink_cwd[PATH_MAX];
|
char readlink_cwd[PATH_MAX];
|
||||||
|
struct timeval zt;
|
||||||
|
fd_set pollfd;
|
||||||
|
|
||||||
|
|
||||||
/* Figure out whether filename is absolute or not */
|
/* Figure out whether filename is absolute or not */
|
||||||
if (filename[0] == '/') {
|
if (filename[0] == '\0') {
|
||||||
|
/* Missing a pathname */
|
||||||
|
return UV_ENOENT;
|
||||||
|
}
|
||||||
|
else if (filename[0] == '/') {
|
||||||
/* We have absolute pathname */
|
/* We have absolute pathname */
|
||||||
snprintf(absolute_path, sizeof(absolute_path), "%s", filename);
|
/* TODO(bnoordhuis) Check uv__strscpy() return value. */
|
||||||
|
uv__strscpy(absolute_path, filename, sizeof(absolute_path));
|
||||||
} else {
|
} else {
|
||||||
/* We have a relative pathname, compose the absolute pathname */
|
/* We have a relative pathname, compose the absolute pathname */
|
||||||
snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid());
|
snprintf(cwd, sizeof(cwd), "/proc/%lu/cwd", (unsigned long) getpid());
|
||||||
@@ -769,6 +774,15 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
|
|
||||||
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
|
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
|
||||||
|
|
||||||
|
/* AHAFS wants someone to poll for it to start mointoring.
|
||||||
|
* so kick-start it so that we don't miss an event in the
|
||||||
|
* eventuality of an event that occurs in the current loop. */
|
||||||
|
do {
|
||||||
|
memset(&zt, 0, sizeof(zt));
|
||||||
|
FD_ZERO(&pollfd);
|
||||||
|
FD_SET(fd, &pollfd);
|
||||||
|
rc = select(fd + 1, &pollfd, NULL, NULL, &zt);
|
||||||
|
} while (rc == -1 && errno == EINTR);
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
return UV_ENOSYS;
|
return UV_ENOSYS;
|
||||||
@@ -886,16 +900,20 @@ int uv_set_process_title(const char* title) {
|
|||||||
|
|
||||||
int uv_get_process_title(char* buffer, size_t size) {
|
int uv_get_process_title(char* buffer, size_t size) {
|
||||||
size_t len;
|
size_t len;
|
||||||
len = strlen(process_argv[0]);
|
|
||||||
if (buffer == NULL || size == 0)
|
if (buffer == NULL || size == 0)
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
else if (size <= len)
|
|
||||||
return UV_ENOBUFS;
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||||
uv_mutex_lock(&process_title_mutex);
|
uv_mutex_lock(&process_title_mutex);
|
||||||
|
|
||||||
memcpy(buffer, process_argv[0], len + 1);
|
len = strlen(process_argv[0]);
|
||||||
|
if (size <= len) {
|
||||||
|
uv_mutex_unlock(&process_title_mutex);
|
||||||
|
return UV_ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, process_argv[0], len);
|
||||||
|
buffer[len] = '\0';
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
uv_mutex_unlock(&process_title_mutex);
|
||||||
|
|
||||||
@@ -982,7 +1000,8 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
|||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(cpu_id.name, FIRST_CPU);
|
/* TODO(bnoordhuis) Check uv__strscpy() return value. */
|
||||||
|
uv__strscpy(cpu_id.name, FIRST_CPU, sizeof(cpu_id.name));
|
||||||
result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
|
result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
uv__free(ps_cpus);
|
uv__free(ps_cpus);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "android-ifaddrs.h"
|
#include "uv/android-ifaddrs.h"
|
||||||
#include "uv-common.h"
|
#include "uv-common.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -52,13 +52,10 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
|||||||
*/
|
*/
|
||||||
if (ent->ifa_addr->sa_family == AF_LINK)
|
if (ent->ifa_addr->sa_family == AF_LINK)
|
||||||
return 1;
|
return 1;
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
if (ent->ifa_addr->sa_family != PF_INET &&
|
if (ent->ifa_addr->sa_family != PF_INET &&
|
||||||
ent->ifa_addr->sa_family != PF_INET6)
|
ent->ifa_addr->sa_family != PF_INET6)
|
||||||
return 1;
|
return 1;
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
if (ent->ifa_addr->sa_family != PF_INET)
|
|
||||||
return 1;
|
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -69,11 +66,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
uv_interface_address_t* address;
|
uv_interface_address_t* address;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
*addresses = NULL;
|
||||||
|
|
||||||
if (getifaddrs(&addrs) != 0)
|
if (getifaddrs(&addrs) != 0)
|
||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
/* Count the number of interfaces */
|
/* Count the number of interfaces */
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||||
@@ -81,6 +79,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*count == 0) {
|
||||||
|
freeifaddrs(addrs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*addresses = uv__malloc(*count * sizeof(**addresses));
|
*addresses = uv__malloc(*count * sizeof(**addresses));
|
||||||
|
|
||||||
if (*addresses == NULL) {
|
if (*addresses == NULL) {
|
||||||
@@ -121,15 +124,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
address = *addresses;
|
address = *addresses;
|
||||||
|
|
||||||
for (i = 0; i < *count; i++) {
|
for (i = 0; i < *count; i++) {
|
||||||
if (strcmp(address->name, ent->ifa_name) == 0) {
|
|
||||||
#if defined(__CYGWIN__) || defined(__MSYS__)
|
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||||
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||||
#else
|
#else
|
||||||
|
if (strcmp(address->name, ent->ifa_name) == 0) {
|
||||||
struct sockaddr_dl* sa_addr;
|
struct sockaddr_dl* sa_addr;
|
||||||
sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
|
sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
|
||||||
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
|
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
|
||||||
#endif
|
} else {
|
||||||
|
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/* Copyright libuv project contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
static uv_mutex_t process_title_mutex;
|
||||||
|
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
||||||
|
static char* process_title;
|
||||||
|
|
||||||
|
|
||||||
|
static void init_process_title_mutex_once(void) {
|
||||||
|
if (uv_mutex_init(&process_title_mutex))
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char** uv_setup_args(int argc, char** argv) {
|
||||||
|
process_title = argc > 0 ? uv__strdup(argv[0]) : NULL;
|
||||||
|
return argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_set_process_title(const char* title) {
|
||||||
|
char* new_title;
|
||||||
|
|
||||||
|
new_title = uv__strdup(title);
|
||||||
|
if (new_title == NULL)
|
||||||
|
return UV_ENOMEM;
|
||||||
|
|
||||||
|
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||||
|
uv_mutex_lock(&process_title_mutex);
|
||||||
|
|
||||||
|
uv__free(process_title);
|
||||||
|
process_title = new_title;
|
||||||
|
setproctitle("%s", title);
|
||||||
|
|
||||||
|
uv_mutex_unlock(&process_title_mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_get_process_title(char* buffer, size_t size) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (buffer == NULL || size == 0)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||||
|
uv_mutex_lock(&process_title_mutex);
|
||||||
|
|
||||||
|
if (process_title != NULL) {
|
||||||
|
len = strlen(process_title) + 1;
|
||||||
|
|
||||||
|
if (size < len) {
|
||||||
|
uv_mutex_unlock(&process_title_mutex);
|
||||||
|
return UV_ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, process_title, len);
|
||||||
|
} else {
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_mutex_unlock(&process_title_mutex);
|
||||||
|
|
||||||
|
buffer[len] = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <sys/resource.h> /* getrusage */
|
#include <sys/resource.h> /* getrusage */
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
#ifdef __sun
|
#ifdef __sun
|
||||||
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
|
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
|
||||||
@@ -119,7 +120,7 @@ uint64_t uv_hrtime(void) {
|
|||||||
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
||||||
assert(!uv__is_closing(handle));
|
assert(!uv__is_closing(handle));
|
||||||
|
|
||||||
handle->flags |= UV_CLOSING;
|
handle->flags |= UV_HANDLE_CLOSING;
|
||||||
handle->close_cb = close_cb;
|
handle->close_cb = close_cb;
|
||||||
|
|
||||||
switch (handle->type) {
|
switch (handle->type) {
|
||||||
@@ -177,8 +178,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
|||||||
|
|
||||||
case UV_SIGNAL:
|
case UV_SIGNAL:
|
||||||
uv__signal_close((uv_signal_t*) handle);
|
uv__signal_close((uv_signal_t*) handle);
|
||||||
/* Signal handles may not be closed immediately. The signal code will */
|
/* Signal handles may not be closed immediately. The signal code will
|
||||||
/* itself close uv__make_close_pending whenever appropriate. */
|
* itself close uv__make_close_pending whenever appropriate. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -217,8 +218,8 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void uv__make_close_pending(uv_handle_t* handle) {
|
void uv__make_close_pending(uv_handle_t* handle) {
|
||||||
assert(handle->flags & UV_CLOSING);
|
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||||
assert(!(handle->flags & UV_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
handle->next_closing = handle->loop->closing_handles;
|
handle->next_closing = handle->loop->closing_handles;
|
||||||
handle->loop->closing_handles = handle;
|
handle->loop->closing_handles = handle;
|
||||||
}
|
}
|
||||||
@@ -244,15 +245,17 @@ int uv__getiovmax(void) {
|
|||||||
|
|
||||||
|
|
||||||
static void uv__finish_close(uv_handle_t* handle) {
|
static void uv__finish_close(uv_handle_t* handle) {
|
||||||
/* Note: while the handle is in the UV_CLOSING state now, it's still possible
|
/* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
|
||||||
* for it to be active in the sense that uv__is_active() returns true.
|
* possible for it to be active in the sense that uv__is_active() returns
|
||||||
|
* true.
|
||||||
|
*
|
||||||
* A good example is when the user calls uv_shutdown(), immediately followed
|
* A good example is when the user calls uv_shutdown(), immediately followed
|
||||||
* by uv_close(). The handle is considered active at this point because the
|
* by uv_close(). The handle is considered active at this point because the
|
||||||
* completion of the shutdown req is still pending.
|
* completion of the shutdown req is still pending.
|
||||||
*/
|
*/
|
||||||
assert(handle->flags & UV_CLOSING);
|
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||||
assert(!(handle->flags & UV_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
handle->flags |= UV_CLOSED;
|
handle->flags |= UV_HANDLE_CLOSED;
|
||||||
|
|
||||||
switch (handle->type) {
|
switch (handle->type) {
|
||||||
case UV_PREPARE:
|
case UV_PREPARE:
|
||||||
@@ -637,27 +640,6 @@ int uv__cloexec_fcntl(int fd, int set) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function is not execve-safe, there is a race window
|
|
||||||
* between the call to dup() and fcntl(FD_CLOEXEC).
|
|
||||||
*/
|
|
||||||
int uv__dup(int fd) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
fd = dup(fd);
|
|
||||||
|
|
||||||
if (fd == -1)
|
|
||||||
return UV__ERR(errno);
|
|
||||||
|
|
||||||
err = uv__cloexec(fd, 1);
|
|
||||||
if (err) {
|
|
||||||
uv__close(fd);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
|
ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
|
||||||
struct cmsghdr* cmsg;
|
struct cmsghdr* cmsg;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
@@ -930,6 +912,11 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv__fd_exists(uv_loop_t* loop, int fd) {
|
||||||
|
return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_getrusage(uv_rusage_t* rusage) {
|
int uv_getrusage(uv_rusage_t* rusage) {
|
||||||
struct rusage usage;
|
struct rusage usage;
|
||||||
|
|
||||||
@@ -1343,6 +1330,9 @@ uv_os_fd_t uv_get_osfhandle(int fd) {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uv_open_osfhandle(uv_os_fd_t os_fd) {
|
||||||
|
return os_fd;
|
||||||
|
}
|
||||||
|
|
||||||
uv_pid_t uv_os_getpid(void) {
|
uv_pid_t uv_os_getpid(void) {
|
||||||
return getpid();
|
return getpid();
|
||||||
@@ -1352,3 +1342,87 @@ uv_pid_t uv_os_getpid(void) {
|
|||||||
uv_pid_t uv_os_getppid(void) {
|
uv_pid_t uv_os_getppid(void) {
|
||||||
return getppid();
|
return getppid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_getpriority(uv_pid_t pid, int* priority) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (priority == NULL)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
r = getpriority(PRIO_PROCESS, (int) pid);
|
||||||
|
|
||||||
|
if (r == -1 && errno != 0)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
*priority = r;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_setpriority(uv_pid_t pid, int priority) {
|
||||||
|
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_uname(uv_utsname_t* buffer) {
|
||||||
|
struct utsname buf;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
if (uname(&buf) == -1) {
|
||||||
|
r = UV__ERR(errno);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = uv__strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname));
|
||||||
|
if (r == UV_E2BIG)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
#ifdef _AIX
|
||||||
|
r = snprintf(buffer->release,
|
||||||
|
sizeof(buffer->release),
|
||||||
|
"%s.%s",
|
||||||
|
buf.version,
|
||||||
|
buf.release);
|
||||||
|
if (r >= sizeof(buffer->release)) {
|
||||||
|
r = UV_E2BIG;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
r = uv__strscpy(buffer->release, buf.release, sizeof(buffer->release));
|
||||||
|
if (r == UV_E2BIG)
|
||||||
|
goto error;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
r = uv__strscpy(buffer->version, buf.version, sizeof(buffer->version));
|
||||||
|
if (r == UV_E2BIG)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
#if defined(_AIX) || defined(__PASE__)
|
||||||
|
r = uv__strscpy(buffer->machine, "ppc64", sizeof(buffer->machine));
|
||||||
|
#else
|
||||||
|
r = uv__strscpy(buffer->machine, buf.machine, sizeof(buffer->machine));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (r == UV_E2BIG)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
buffer->sysname[0] = '\0';
|
||||||
|
buffer->release[0] = '\0';
|
||||||
|
buffer->version[0] = '\0';
|
||||||
|
buffer->machine[0] = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ int uv_uptime(double* uptime) {
|
|||||||
int uv_resident_set_memory(size_t* rss) {
|
int uv_resident_set_memory(size_t* rss) {
|
||||||
/* FIXME: read /proc/meminfo? */
|
/* FIXME: read /proc/meminfo? */
|
||||||
*rss = 0;
|
*rss = 0;
|
||||||
return UV_ENOSYS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||||
|
|||||||
@@ -33,61 +33,56 @@
|
|||||||
# include <ApplicationServices/ApplicationServices.h>
|
# include <ApplicationServices/ApplicationServices.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
|
||||||
|
|
||||||
static int uv__pthread_setname_np(const char* name) {
|
|
||||||
int (*dynamic_pthread_setname_np)(const char* name);
|
|
||||||
char namebuf[64]; /* MAXTHREADNAMESIZE */
|
|
||||||
int err;
|
|
||||||
|
|
||||||
|
static int (*dynamic_pthread_setname_np)(const char* name);
|
||||||
|
#if !TARGET_OS_IPHONE
|
||||||
|
static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
||||||
|
const char*,
|
||||||
|
CFStringEncoding);
|
||||||
|
static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
|
||||||
|
static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
|
||||||
|
static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
|
||||||
|
static CFTypeRef (*pLSGetCurrentApplicationASN)(void);
|
||||||
|
static OSStatus (*pLSSetApplicationInformationItem)(int,
|
||||||
|
CFTypeRef,
|
||||||
|
CFStringRef,
|
||||||
|
CFStringRef,
|
||||||
|
CFDictionaryRef*);
|
||||||
|
static void* application_services_handle;
|
||||||
|
static void* core_foundation_handle;
|
||||||
|
static CFBundleRef launch_services_bundle;
|
||||||
|
static CFStringRef* display_name_key;
|
||||||
|
static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
|
||||||
|
static CFBundleRef (*pCFBundleGetMainBundle)(void);
|
||||||
|
static CFBundleRef hi_services_bundle;
|
||||||
|
static OSStatus (*pSetApplicationIsDaemon)(int);
|
||||||
|
static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
|
||||||
|
static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
|
||||||
|
void*);
|
||||||
|
|
||||||
|
|
||||||
|
UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) {
|
||||||
|
if (core_foundation_handle != NULL) {
|
||||||
|
dlclose(core_foundation_handle);
|
||||||
|
core_foundation_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (application_services_handle != NULL) {
|
||||||
|
dlclose(application_services_handle);
|
||||||
|
application_services_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* !TARGET_OS_IPHONE */
|
||||||
|
|
||||||
|
|
||||||
|
void uv__set_process_title_platform_init(void) {
|
||||||
/* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
|
/* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
|
||||||
*(void **)(&dynamic_pthread_setname_np) =
|
*(void **)(&dynamic_pthread_setname_np) =
|
||||||
dlsym(RTLD_DEFAULT, "pthread_setname_np");
|
dlsym(RTLD_DEFAULT, "pthread_setname_np");
|
||||||
|
|
||||||
if (dynamic_pthread_setname_np == NULL)
|
#if !TARGET_OS_IPHONE
|
||||||
return UV_ENOSYS;
|
|
||||||
|
|
||||||
strncpy(namebuf, name, sizeof(namebuf) - 1);
|
|
||||||
namebuf[sizeof(namebuf) - 1] = '\0';
|
|
||||||
|
|
||||||
err = dynamic_pthread_setname_np(namebuf);
|
|
||||||
if (err)
|
|
||||||
return UV__ERR(err);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__set_process_title(const char* title) {
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
return uv__pthread_setname_np(title);
|
|
||||||
#else
|
|
||||||
CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
|
|
||||||
const char*,
|
|
||||||
CFStringEncoding);
|
|
||||||
CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
|
|
||||||
void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
|
|
||||||
void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
|
|
||||||
CFTypeRef (*pLSGetCurrentApplicationASN)(void);
|
|
||||||
OSStatus (*pLSSetApplicationInformationItem)(int,
|
|
||||||
CFTypeRef,
|
|
||||||
CFStringRef,
|
|
||||||
CFStringRef,
|
|
||||||
CFDictionaryRef*);
|
|
||||||
void* application_services_handle;
|
|
||||||
void* core_foundation_handle;
|
|
||||||
CFBundleRef launch_services_bundle;
|
|
||||||
CFStringRef* display_name_key;
|
|
||||||
CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
|
|
||||||
CFBundleRef (*pCFBundleGetMainBundle)(void);
|
|
||||||
CFBundleRef hi_services_bundle;
|
|
||||||
OSStatus (*pSetApplicationIsDaemon)(int);
|
|
||||||
CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
|
|
||||||
void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
|
|
||||||
void*);
|
|
||||||
CFTypeRef asn;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = UV_ENOENT;
|
|
||||||
application_services_handle = dlopen("/System/Library/Frameworks/"
|
application_services_handle = dlopen("/System/Library/Frameworks/"
|
||||||
"ApplicationServices.framework/"
|
"ApplicationServices.framework/"
|
||||||
"Versions/A/ApplicationServices",
|
"Versions/A/ApplicationServices",
|
||||||
@@ -116,8 +111,6 @@ int uv__set_process_title(const char* title) {
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
|
|
||||||
|
|
||||||
launch_services_bundle =
|
launch_services_bundle =
|
||||||
pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
|
pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
|
||||||
|
|
||||||
@@ -148,13 +141,14 @@ int uv__set_process_title(const char* title) {
|
|||||||
"CFBundleGetInfoDictionary");
|
"CFBundleGetInfoDictionary");
|
||||||
*(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle,
|
*(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle,
|
||||||
"CFBundleGetMainBundle");
|
"CFBundleGetMainBundle");
|
||||||
|
|
||||||
if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL)
|
if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
|
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
|
||||||
hi_services_bundle =
|
hi_services_bundle =
|
||||||
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
|
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
|
||||||
err = UV_ENOENT;
|
|
||||||
if (hi_services_bundle == NULL)
|
if (hi_services_bundle == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -168,42 +162,37 @@ int uv__set_process_title(const char* title) {
|
|||||||
pCFBundleGetFunctionPointerForName(
|
pCFBundleGetFunctionPointerForName(
|
||||||
launch_services_bundle,
|
launch_services_bundle,
|
||||||
S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
|
S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
|
||||||
|
|
||||||
if (pSetApplicationIsDaemon == NULL ||
|
if (pSetApplicationIsDaemon == NULL ||
|
||||||
pLSApplicationCheckIn == NULL ||
|
pLSApplicationCheckIn == NULL ||
|
||||||
pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
|
pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSetApplicationIsDaemon(1) != noErr)
|
return;
|
||||||
goto out;
|
|
||||||
|
|
||||||
pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
|
|
||||||
|
|
||||||
/* Check into process manager?! */
|
|
||||||
pLSApplicationCheckIn(-2,
|
|
||||||
pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
|
|
||||||
|
|
||||||
asn = pLSGetCurrentApplicationASN();
|
|
||||||
|
|
||||||
err = UV_EINVAL;
|
|
||||||
if (pLSSetApplicationInformationItem(-2, /* Magic value. */
|
|
||||||
asn,
|
|
||||||
*display_name_key,
|
|
||||||
S(title),
|
|
||||||
NULL) != noErr) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__pthread_setname_np(title); /* Don't care if it fails. */
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (core_foundation_handle != NULL)
|
uv__set_process_title_platform_fini();
|
||||||
dlclose(core_foundation_handle);
|
|
||||||
|
|
||||||
if (application_services_handle != NULL)
|
|
||||||
dlclose(application_services_handle);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
#endif /* !TARGET_OS_IPHONE */
|
#endif /* !TARGET_OS_IPHONE */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uv__set_process_title(const char* title) {
|
||||||
|
#if !TARGET_OS_IPHONE
|
||||||
|
if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) {
|
||||||
|
CFTypeRef asn;
|
||||||
|
pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
|
||||||
|
pLSApplicationCheckIn(/* Magic value */ -2,
|
||||||
|
pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
|
||||||
|
asn = pLSGetCurrentApplicationASN();
|
||||||
|
pLSSetApplicationInformationItem(/* Magic value */ -2, asn,
|
||||||
|
*display_name_key, S(title), NULL);
|
||||||
|
}
|
||||||
|
#endif /* !TARGET_OS_IPHONE */
|
||||||
|
|
||||||
|
if (dynamic_pthread_setname_np != NULL) {
|
||||||
|
char namebuf[64]; /* MAXTHREADNAMESIZE */
|
||||||
|
uv__strscpy(namebuf, title, sizeof(namebuf));
|
||||||
|
dynamic_pthread_setname_np(namebuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,15 +47,6 @@
|
|||||||
# define CP_INTR 4
|
# define CP_INTR 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uv_mutex_t process_title_mutex;
|
|
||||||
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
|
||||||
static char *process_title;
|
|
||||||
|
|
||||||
|
|
||||||
static void init_process_title_mutex_once(void) {
|
|
||||||
uv_mutex_init(&process_title_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||||
return uv__kqueue_init(loop);
|
return uv__kqueue_init(loop);
|
||||||
@@ -159,76 +150,6 @@ void uv_loadavg(double avg[3]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char** uv_setup_args(int argc, char** argv) {
|
|
||||||
process_title = argc ? uv__strdup(argv[0]) : NULL;
|
|
||||||
return argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_set_process_title(const char* title) {
|
|
||||||
int oid[4];
|
|
||||||
char* new_title;
|
|
||||||
|
|
||||||
new_title = uv__strdup(title);
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
||||||
uv_mutex_lock(&process_title_mutex);
|
|
||||||
|
|
||||||
if (process_title == NULL) {
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
return UV_ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(process_title);
|
|
||||||
process_title = new_title;
|
|
||||||
|
|
||||||
oid[0] = CTL_KERN;
|
|
||||||
oid[1] = KERN_PROC;
|
|
||||||
oid[2] = KERN_PROC_ARGS;
|
|
||||||
oid[3] = getpid();
|
|
||||||
|
|
||||||
sysctl(oid,
|
|
||||||
ARRAY_SIZE(oid),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
process_title,
|
|
||||||
strlen(process_title) + 1);
|
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_get_process_title(char* buffer, size_t size) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (buffer == NULL || size == 0)
|
|
||||||
return UV_EINVAL;
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
||||||
uv_mutex_lock(&process_title_mutex);
|
|
||||||
|
|
||||||
if (process_title) {
|
|
||||||
len = strlen(process_title) + 1;
|
|
||||||
|
|
||||||
if (size < len) {
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
return UV_ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, process_title, len);
|
|
||||||
} else {
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
|
|
||||||
buffer[len] = '\0';
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int uv_resident_set_memory(size_t* rss) {
|
int uv_resident_set_memory(size_t* rss) {
|
||||||
struct kinfo_proc kinfo;
|
struct kinfo_proc kinfo;
|
||||||
size_t page_size;
|
size_t page_size;
|
||||||
|
|||||||
+165
-134
@@ -43,7 +43,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <utime.h>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
#if defined(__DragonFly__) || \
|
#if defined(__DragonFly__) || \
|
||||||
@@ -62,11 +61,20 @@
|
|||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
# include <copyfile.h>
|
# include <copyfile.h>
|
||||||
|
# include <sys/sysctl.h>
|
||||||
#elif defined(__linux__) && !defined(FICLONE)
|
#elif defined(__linux__) && !defined(FICLONE)
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
# define FICLONE _IOW(0x94, 9, int)
|
# define FICLONE _IOW(0x94, 9, int)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_AIX) && !defined(_AIX71)
|
||||||
|
# include <utime.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_AIX) && _XOPEN_SOURCE <= 600
|
||||||
|
extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INIT(subtype) \
|
#define INIT(subtype) \
|
||||||
do { \
|
do { \
|
||||||
if (req == NULL) \
|
if (req == NULL) \
|
||||||
@@ -120,7 +128,11 @@
|
|||||||
do { \
|
do { \
|
||||||
if (cb != NULL) { \
|
if (cb != NULL) { \
|
||||||
uv__req_register(loop, req); \
|
uv__req_register(loop, req); \
|
||||||
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
|
uv__work_submit(loop, \
|
||||||
|
&req->work_req, \
|
||||||
|
UV__WORK_FAST_IO, \
|
||||||
|
uv__fs_work, \
|
||||||
|
uv__fs_done); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
@@ -143,7 +155,7 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) {
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = fcntl(req->file, F_FULLFSYNC);
|
r = fcntl(req->file, F_FULLFSYNC);
|
||||||
if (r != 0 && errno == ENOTTY)
|
if (r != 0)
|
||||||
r = fsync(req->file);
|
r = fsync(req->file);
|
||||||
return r;
|
return r;
|
||||||
#else
|
#else
|
||||||
@@ -165,59 +177,17 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
|||||||
|
|
||||||
|
|
||||||
static ssize_t uv__fs_futime(uv_fs_t* req) {
|
static ssize_t uv__fs_futime(uv_fs_t* req) {
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) \
|
||||||
|
|| defined(_AIX71)
|
||||||
/* utimesat() has nanosecond resolution but we stick to microseconds
|
/* utimesat() has nanosecond resolution but we stick to microseconds
|
||||||
* for the sake of consistency with other platforms.
|
* for the sake of consistency with other platforms.
|
||||||
*/
|
*/
|
||||||
static int no_utimesat;
|
|
||||||
struct timespec ts[2];
|
struct timespec ts[2];
|
||||||
struct timeval tv[2];
|
|
||||||
char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)];
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (no_utimesat)
|
|
||||||
goto skip;
|
|
||||||
|
|
||||||
ts[0].tv_sec = req->atime;
|
ts[0].tv_sec = req->atime;
|
||||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
||||||
ts[1].tv_sec = req->mtime;
|
ts[1].tv_sec = req->mtime;
|
||||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
||||||
|
return futimens(req->file, ts);
|
||||||
r = uv__utimesat(req->file, NULL, ts, 0);
|
|
||||||
if (r == 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (errno != ENOSYS)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
no_utimesat = 1;
|
|
||||||
|
|
||||||
skip:
|
|
||||||
|
|
||||||
tv[0].tv_sec = req->atime;
|
|
||||||
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
|
||||||
tv[1].tv_sec = req->mtime;
|
|
||||||
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
|
||||||
snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file);
|
|
||||||
|
|
||||||
r = utimes(path, tv);
|
|
||||||
if (r == 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
switch (errno) {
|
|
||||||
case ENOENT:
|
|
||||||
if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF)
|
|
||||||
break;
|
|
||||||
/* Fall through. */
|
|
||||||
|
|
||||||
case EACCES:
|
|
||||||
case ENOTDIR:
|
|
||||||
errno = ENOSYS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
|
|
||||||
#elif defined(__APPLE__) \
|
#elif defined(__APPLE__) \
|
||||||
|| defined(__DragonFly__) \
|
|| defined(__DragonFly__) \
|
||||||
|| defined(__FreeBSD__) \
|
|| defined(__FreeBSD__) \
|
||||||
@@ -235,13 +205,6 @@ skip:
|
|||||||
# else
|
# else
|
||||||
return futimes(req->file, tv);
|
return futimes(req->file, tv);
|
||||||
# endif
|
# endif
|
||||||
#elif defined(_AIX71)
|
|
||||||
struct timespec ts[2];
|
|
||||||
ts[0].tv_sec = req->atime;
|
|
||||||
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
|
||||||
ts[1].tv_sec = req->mtime;
|
|
||||||
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
|
||||||
return futimens(req->file, ts);
|
|
||||||
#elif defined(__MVS__)
|
#elif defined(__MVS__)
|
||||||
attrib_t atr;
|
attrib_t atr;
|
||||||
memset(&atr, 0, sizeof(atr));
|
memset(&atr, 0, sizeof(atr));
|
||||||
@@ -314,17 +277,13 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
static int no_preadv;
|
static int no_preadv;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned int iovmax;
|
||||||
ssize_t result;
|
ssize_t result;
|
||||||
|
|
||||||
#if defined(_AIX)
|
iovmax = uv__getiovmax();
|
||||||
struct stat buf;
|
if (req->nbufs > iovmax)
|
||||||
if(fstat(req->file, &buf))
|
req->nbufs = iovmax;
|
||||||
return -1;
|
|
||||||
if(S_ISDIR(buf.st_mode)) {
|
|
||||||
errno = EISDIR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif /* defined(_AIX) */
|
|
||||||
if (req->off < 0) {
|
if (req->off < 0) {
|
||||||
if (req->nbufs == 1)
|
if (req->nbufs == 1)
|
||||||
result = read(req->file, req->bufs[0].base, req->bufs[0].len);
|
result = read(req->file, req->bufs[0].base, req->bufs[0].len);
|
||||||
@@ -343,25 +302,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
|||||||
if (no_preadv) retry:
|
if (no_preadv) retry:
|
||||||
# endif
|
# endif
|
||||||
{
|
{
|
||||||
off_t nread;
|
result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
|
||||||
size_t index;
|
|
||||||
|
|
||||||
nread = 0;
|
|
||||||
index = 0;
|
|
||||||
result = 1;
|
|
||||||
do {
|
|
||||||
if (req->bufs[index].len > 0) {
|
|
||||||
result = pread(req->file,
|
|
||||||
req->bufs[index].base,
|
|
||||||
req->bufs[index].len,
|
|
||||||
req->off + nread);
|
|
||||||
if (result > 0)
|
|
||||||
nread += result;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
} while (index < req->nbufs && result > 0);
|
|
||||||
if (nread > 0)
|
|
||||||
result = nread;
|
|
||||||
}
|
}
|
||||||
# if defined(__linux__)
|
# if defined(__linux__)
|
||||||
else {
|
else {
|
||||||
@@ -379,6 +320,13 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
/* Early cleanup of bufs allocation, since we're done with it. */
|
||||||
|
if (req->bufs != req->bufsml)
|
||||||
|
uv__free(req->bufs);
|
||||||
|
|
||||||
|
req->bufs = NULL;
|
||||||
|
req->nbufs = 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,8 +394,10 @@ static ssize_t uv__fs_pathmax_size(const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||||
|
ssize_t maxlen;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
char* buf;
|
char* buf;
|
||||||
|
char* newbuf;
|
||||||
|
|
||||||
#if defined(UV__FS_PATH_MAX_FALLBACK)
|
#if defined(UV__FS_PATH_MAX_FALLBACK)
|
||||||
/* We may not have a real PATH_MAX. Read size of link. */
|
/* We may not have a real PATH_MAX. Read size of link. */
|
||||||
@@ -461,17 +411,17 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = st.st_size;
|
maxlen = st.st_size;
|
||||||
|
|
||||||
/* According to readlink(2) lstat can report st_size == 0
|
/* According to readlink(2) lstat can report st_size == 0
|
||||||
for some symlinks, such as those in /proc or /sys. */
|
for some symlinks, such as those in /proc or /sys. */
|
||||||
if (len == 0)
|
if (maxlen == 0)
|
||||||
len = uv__fs_pathmax_size(req->path);
|
maxlen = uv__fs_pathmax_size(req->path);
|
||||||
#else
|
#else
|
||||||
len = uv__fs_pathmax_size(req->path);
|
maxlen = uv__fs_pathmax_size(req->path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
buf = uv__malloc(len + 1);
|
buf = uv__malloc(maxlen);
|
||||||
|
|
||||||
if (buf == NULL) {
|
if (buf == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
@@ -479,17 +429,28 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__MVS__)
|
#if defined(__MVS__)
|
||||||
len = os390_readlink(req->path, buf, len);
|
len = os390_readlink(req->path, buf, maxlen);
|
||||||
#else
|
#else
|
||||||
len = readlink(req->path, buf, len);
|
len = readlink(req->path, buf, maxlen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
uv__free(buf);
|
uv__free(buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Uncommon case: resize to make room for the trailing nul byte. */
|
||||||
|
if (len == maxlen) {
|
||||||
|
newbuf = uv__realloc(buf, len + 1);
|
||||||
|
|
||||||
|
if (newbuf == NULL) {
|
||||||
|
uv__free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = newbuf;
|
||||||
|
}
|
||||||
|
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
req->ptr = buf;
|
req->ptr = buf;
|
||||||
|
|
||||||
@@ -739,10 +700,48 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
|
|||||||
|
|
||||||
|
|
||||||
static ssize_t uv__fs_utime(uv_fs_t* req) {
|
static ssize_t uv__fs_utime(uv_fs_t* req) {
|
||||||
|
#if defined(__linux__) \
|
||||||
|
|| defined(_AIX71) \
|
||||||
|
|| defined(__sun)
|
||||||
|
/* utimesat() has nanosecond resolution but we stick to microseconds
|
||||||
|
* for the sake of consistency with other platforms.
|
||||||
|
*/
|
||||||
|
struct timespec ts[2];
|
||||||
|
ts[0].tv_sec = req->atime;
|
||||||
|
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
|
||||||
|
ts[1].tv_sec = req->mtime;
|
||||||
|
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
|
||||||
|
return utimensat(AT_FDCWD, req->path, ts, 0);
|
||||||
|
#elif defined(__APPLE__) \
|
||||||
|
|| defined(__DragonFly__) \
|
||||||
|
|| defined(__FreeBSD__) \
|
||||||
|
|| defined(__FreeBSD_kernel__) \
|
||||||
|
|| defined(__NetBSD__) \
|
||||||
|
|| defined(__OpenBSD__)
|
||||||
|
struct timeval tv[2];
|
||||||
|
tv[0].tv_sec = req->atime;
|
||||||
|
tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
|
||||||
|
tv[1].tv_sec = req->mtime;
|
||||||
|
tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
|
||||||
|
return utimes(req->path, tv);
|
||||||
|
#elif defined(_AIX) \
|
||||||
|
&& !defined(_AIX71)
|
||||||
struct utimbuf buf;
|
struct utimbuf buf;
|
||||||
buf.actime = req->atime;
|
buf.actime = req->atime;
|
||||||
buf.modtime = req->mtime;
|
buf.modtime = req->mtime;
|
||||||
return utime(req->path, &buf); /* TODO use utimes() where available */
|
return utime(req->path, &buf);
|
||||||
|
#elif defined(__MVS__)
|
||||||
|
attrib_t atr;
|
||||||
|
memset(&atr, 0, sizeof(atr));
|
||||||
|
atr.att_mtimechg = 1;
|
||||||
|
atr.att_atimechg = 1;
|
||||||
|
atr.att_mtime = req->mtime;
|
||||||
|
atr.att_atime = req->atime;
|
||||||
|
return __lchattr((char*) req->path, &atr, sizeof(atr));
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -780,25 +779,7 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
|
|||||||
if (no_pwritev) retry:
|
if (no_pwritev) retry:
|
||||||
# endif
|
# endif
|
||||||
{
|
{
|
||||||
off_t written;
|
r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
|
||||||
size_t index;
|
|
||||||
|
|
||||||
written = 0;
|
|
||||||
index = 0;
|
|
||||||
r = 0;
|
|
||||||
do {
|
|
||||||
if (req->bufs[index].len > 0) {
|
|
||||||
r = pwrite(req->file,
|
|
||||||
req->bufs[index].base,
|
|
||||||
req->bufs[index].len,
|
|
||||||
req->off + written);
|
|
||||||
if (r > 0)
|
|
||||||
written += r;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
} while (index < req->nbufs && r >= 0);
|
|
||||||
if (written > 0)
|
|
||||||
r = written;
|
|
||||||
}
|
}
|
||||||
# if defined(__linux__)
|
# if defined(__linux__)
|
||||||
else {
|
else {
|
||||||
@@ -827,26 +808,41 @@ done:
|
|||||||
static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||||
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
||||||
/* On macOS, use the native copyfile(3). */
|
/* On macOS, use the native copyfile(3). */
|
||||||
|
static int can_clone;
|
||||||
copyfile_flags_t flags;
|
copyfile_flags_t flags;
|
||||||
|
char buf[64];
|
||||||
|
size_t len;
|
||||||
|
int major;
|
||||||
|
|
||||||
flags = COPYFILE_ALL;
|
flags = COPYFILE_ALL;
|
||||||
|
|
||||||
if (req->flags & UV_FS_COPYFILE_EXCL)
|
if (req->flags & UV_FS_COPYFILE_EXCL)
|
||||||
flags |= COPYFILE_EXCL;
|
flags |= COPYFILE_EXCL;
|
||||||
|
|
||||||
#ifdef COPYFILE_CLONE
|
/* Check OS version. Cloning is only supported on macOS >= 10.12. */
|
||||||
if (req->flags & UV_FS_COPYFILE_FICLONE)
|
|
||||||
flags |= COPYFILE_CLONE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
#ifdef COPYFILE_CLONE_FORCE
|
if (can_clone == 0) {
|
||||||
flags |= COPYFILE_CLONE_FORCE;
|
len = sizeof(buf);
|
||||||
#else
|
if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0))
|
||||||
return UV_ENOSYS;
|
return UV__ERR(errno);
|
||||||
#endif
|
|
||||||
|
if (1 != sscanf(buf, "%d", &major))
|
||||||
|
abort();
|
||||||
|
|
||||||
|
can_clone = -1 + 2 * (major >= 16); /* macOS >= 10.12 */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can_clone < 0)
|
||||||
|
return UV_ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */
|
||||||
|
if (req->flags & UV_FS_COPYFILE_FICLONE)
|
||||||
|
flags |= 1 << 24; /* COPYFILE_CLONE */
|
||||||
|
|
||||||
|
if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE)
|
||||||
|
flags |= 1 << 25; /* COPYFILE_CLONE_FORCE */
|
||||||
|
|
||||||
return copyfile(req->path, req->new_path, NULL, flags);
|
return copyfile(req->path, req->new_path, NULL, flags);
|
||||||
#else
|
#else
|
||||||
uv_fs_t fs_req;
|
uv_fs_t fs_req;
|
||||||
@@ -906,9 +902,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
|||||||
/* If an error occurred that the sendfile fallback also won't handle, or
|
/* If an error occurred that the sendfile fallback also won't handle, or
|
||||||
this is a force clone then exit. Otherwise, fall through to try using
|
this is a force clone then exit. Otherwise, fall through to try using
|
||||||
sendfile(). */
|
sendfile(). */
|
||||||
if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
|
if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
|
||||||
req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
err = UV__ERR(errno);
|
||||||
err = -errno;
|
goto out;
|
||||||
|
} else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
|
||||||
|
err = UV_ENOTSUP;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -968,7 +966,11 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
if (result == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
errno = UV__ERR(result);
|
||||||
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,9 +1086,21 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) {
|
||||||
|
size_t offset;
|
||||||
|
/* Figure out which bufs are done */
|
||||||
|
for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset)
|
||||||
|
size -= bufs[offset].len;
|
||||||
|
|
||||||
typedef ssize_t (*uv__fs_buf_iter_processor)(uv_fs_t* req);
|
/* Fix a partial read/write */
|
||||||
static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) {
|
if (size > 0) {
|
||||||
|
bufs[offset].base += size;
|
||||||
|
bufs[offset].len -= size;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t uv__fs_write_all(uv_fs_t* req) {
|
||||||
unsigned int iovmax;
|
unsigned int iovmax;
|
||||||
unsigned int nbufs;
|
unsigned int nbufs;
|
||||||
uv_buf_t* bufs;
|
uv_buf_t* bufs;
|
||||||
@@ -1103,7 +1117,10 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
|
|||||||
if (req->nbufs > iovmax)
|
if (req->nbufs > iovmax)
|
||||||
req->nbufs = iovmax;
|
req->nbufs = iovmax;
|
||||||
|
|
||||||
result = process(req);
|
do
|
||||||
|
result = uv__fs_write(req);
|
||||||
|
while (result < 0 && errno == EINTR);
|
||||||
|
|
||||||
if (result <= 0) {
|
if (result <= 0) {
|
||||||
if (total == 0)
|
if (total == 0)
|
||||||
total = result;
|
total = result;
|
||||||
@@ -1113,14 +1130,12 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
|
|||||||
if (req->off >= 0)
|
if (req->off >= 0)
|
||||||
req->off += result;
|
req->off += result;
|
||||||
|
|
||||||
|
req->nbufs = uv__fs_buf_offset(req->bufs, result);
|
||||||
req->bufs += req->nbufs;
|
req->bufs += req->nbufs;
|
||||||
nbufs -= req->nbufs;
|
nbufs -= req->nbufs;
|
||||||
total += result;
|
total += result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno == EINTR && total == -1)
|
|
||||||
return total;
|
|
||||||
|
|
||||||
if (bufs != req->bufsml)
|
if (bufs != req->bufsml)
|
||||||
uv__free(bufs);
|
uv__free(bufs);
|
||||||
|
|
||||||
@@ -1137,7 +1152,8 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
ssize_t r;
|
ssize_t r;
|
||||||
|
|
||||||
req = container_of(w, uv_fs_t, work_req);
|
req = container_of(w, uv_fs_t, work_req);
|
||||||
retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
|
retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
|
||||||
|
req->fs_type == UV_FS_READ);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -1155,6 +1171,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
X(COPYFILE, uv__fs_copyfile(req));
|
X(COPYFILE, uv__fs_copyfile(req));
|
||||||
X(FCHMOD, fchmod(req->file, req->mode));
|
X(FCHMOD, fchmod(req->file, req->mode));
|
||||||
X(FCHOWN, fchown(req->file, req->uid, req->gid));
|
X(FCHOWN, fchown(req->file, req->uid, req->gid));
|
||||||
|
X(LCHOWN, lchown(req->path, req->uid, req->gid));
|
||||||
X(FDATASYNC, uv__fs_fdatasync(req));
|
X(FDATASYNC, uv__fs_fdatasync(req));
|
||||||
X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
|
X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
|
||||||
X(FSYNC, uv__fs_fsync(req));
|
X(FSYNC, uv__fs_fsync(req));
|
||||||
@@ -1165,7 +1182,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
X(MKDIR, mkdir(req->path, req->mode));
|
X(MKDIR, mkdir(req->path, req->mode));
|
||||||
X(MKDTEMP, uv__fs_mkdtemp(req));
|
X(MKDTEMP, uv__fs_mkdtemp(req));
|
||||||
X(OPEN, uv__fs_open(req));
|
X(OPEN, uv__fs_open(req));
|
||||||
X(READ, uv__fs_buf_iter(req, uv__fs_read));
|
X(READ, uv__fs_read(req));
|
||||||
X(SCANDIR, uv__fs_scandir(req));
|
X(SCANDIR, uv__fs_scandir(req));
|
||||||
X(READLINK, uv__fs_readlink(req));
|
X(READLINK, uv__fs_readlink(req));
|
||||||
X(REALPATH, uv__fs_realpath(req));
|
X(REALPATH, uv__fs_realpath(req));
|
||||||
@@ -1176,7 +1193,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
X(SYMLINK, symlink(req->path, req->new_path));
|
X(SYMLINK, symlink(req->path, req->new_path));
|
||||||
X(UNLINK, unlink(req->path));
|
X(UNLINK, unlink(req->path));
|
||||||
X(UTIME, uv__fs_utime(req));
|
X(UTIME, uv__fs_utime(req));
|
||||||
X(WRITE, uv__fs_buf_iter(req, uv__fs_write));
|
X(WRITE, uv__fs_write_all(req));
|
||||||
default: abort();
|
default: abort();
|
||||||
}
|
}
|
||||||
#undef X
|
#undef X
|
||||||
@@ -1281,6 +1298,20 @@ int uv_fs_fchown(uv_loop_t* loop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_fs_lchown(uv_loop_t* loop,
|
||||||
|
uv_fs_t* req,
|
||||||
|
const char* path,
|
||||||
|
uv_uid_t uid,
|
||||||
|
uv_gid_t gid,
|
||||||
|
uv_fs_cb cb) {
|
||||||
|
INIT(LCHOWN);
|
||||||
|
PATH;
|
||||||
|
req->uid = uid;
|
||||||
|
req->gid = gid;
|
||||||
|
POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||||
INIT(FDATASYNC);
|
INIT(FDATASYNC);
|
||||||
req->file = file;
|
req->file = file;
|
||||||
|
|||||||
@@ -255,42 +255,55 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
|||||||
path = paths[i];
|
path = paths[i];
|
||||||
len = strlen(path);
|
len = strlen(path);
|
||||||
|
|
||||||
|
if (handle->realpath_len == 0)
|
||||||
|
continue; /* This should be unreachable */
|
||||||
|
|
||||||
/* Filter out paths that are outside handle's request */
|
/* Filter out paths that are outside handle's request */
|
||||||
if (strncmp(path, handle->realpath, handle->realpath_len) != 0)
|
if (len < handle->realpath_len)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (handle->realpath_len > 1 || *handle->realpath != '/') {
|
if (handle->realpath_len != len &&
|
||||||
|
path[handle->realpath_len] != '/')
|
||||||
|
/* Make sure that realpath actually named a directory,
|
||||||
|
* or that we matched the whole string */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (memcmp(path, handle->realpath, handle->realpath_len) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(handle->realpath_len == 1 && handle->realpath[0] == '/')) {
|
||||||
|
/* Remove common prefix, unless the watched folder is "/" */
|
||||||
path += handle->realpath_len;
|
path += handle->realpath_len;
|
||||||
len -= handle->realpath_len;
|
len -= handle->realpath_len;
|
||||||
|
|
||||||
/* Skip forward slash */
|
/* Ignore events with path equal to directory itself */
|
||||||
if (*path != '\0') {
|
if (len <= 1 && (flags & kFSEventStreamEventFlagItemIsDir))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
/* Since we're using fsevents to watch the file itself,
|
||||||
|
* realpath == path, and we now need to get the basename of the file back
|
||||||
|
* (for commonality with other codepaths and platforms). */
|
||||||
|
while (len < handle->realpath_len && path[-1] != '/') {
|
||||||
|
path--;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
/* Created and Removed seem to be always set, but don't make sense */
|
||||||
|
flags &= ~kFSEventsRenamed;
|
||||||
|
} else {
|
||||||
|
/* Skip forward slash */
|
||||||
path++;
|
path++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAC_OS_X_VERSION_10_7
|
|
||||||
/* Ignore events with path equal to directory itself */
|
|
||||||
if (len == 0)
|
|
||||||
continue;
|
|
||||||
#else
|
|
||||||
if (len == 0 && (flags & kFSEventStreamEventFlagItemIsDir))
|
|
||||||
continue;
|
|
||||||
#endif /* MAC_OS_X_VERSION_10_7 */
|
|
||||||
|
|
||||||
/* Do not emit events from subdirectories (without option set) */
|
/* Do not emit events from subdirectories (without option set) */
|
||||||
if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != 0) {
|
if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != '\0') {
|
||||||
pos = strchr(path + 1, '/');
|
pos = strchr(path + 1, '/');
|
||||||
if (pos != NULL)
|
if (pos != NULL)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef MAC_OS_X_VERSION_10_7
|
|
||||||
path = "";
|
|
||||||
len = 0;
|
|
||||||
#endif /* MAC_OS_X_VERSION_10_7 */
|
|
||||||
|
|
||||||
event = uv__malloc(sizeof(*event) + len);
|
event = uv__malloc(sizeof(*event) + len);
|
||||||
if (event == NULL)
|
if (event == NULL)
|
||||||
break;
|
break;
|
||||||
@@ -299,22 +312,11 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
|||||||
memcpy(event->path, path, len + 1);
|
memcpy(event->path, path, len + 1);
|
||||||
event->events = UV_RENAME;
|
event->events = UV_RENAME;
|
||||||
|
|
||||||
#ifdef MAC_OS_X_VERSION_10_7
|
if (0 == (flags & kFSEventsRenamed)) {
|
||||||
if (0 != (flags & kFSEventsModified) &&
|
if (0 != (flags & kFSEventsModified) ||
|
||||||
0 == (flags & kFSEventsRenamed)) {
|
0 == (flags & kFSEventStreamEventFlagItemIsDir))
|
||||||
event->events = UV_CHANGE;
|
event->events = UV_CHANGE;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (0 != (flags & kFSEventsModified) &&
|
|
||||||
0 != (flags & kFSEventStreamEventFlagItemIsDir) &&
|
|
||||||
0 == (flags & kFSEventStreamEventFlagItemRenamed)) {
|
|
||||||
event->events = UV_CHANGE;
|
|
||||||
}
|
|
||||||
if (0 == (flags & kFSEventStreamEventFlagItemIsDir) &&
|
|
||||||
0 == (flags & kFSEventStreamEventFlagItemRenamed)) {
|
|
||||||
event->events = UV_CHANGE;
|
|
||||||
}
|
|
||||||
#endif /* MAC_OS_X_VERSION_10_7 */
|
|
||||||
|
|
||||||
QUEUE_INSERT_TAIL(&head, &event->member);
|
QUEUE_INSERT_TAIL(&head, &event->member);
|
||||||
}
|
}
|
||||||
@@ -836,7 +838,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
|
|||||||
|
|
||||||
handle->cf_cb->data = handle;
|
handle->cf_cb->data = handle;
|
||||||
uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb);
|
uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb);
|
||||||
handle->cf_cb->flags |= UV__HANDLE_INTERNAL;
|
handle->cf_cb->flags |= UV_HANDLE_INTERNAL;
|
||||||
uv_unref((uv_handle_t*) handle->cf_cb);
|
uv_unref((uv_handle_t*) handle->cf_cb);
|
||||||
|
|
||||||
err = uv_mutex_init(&handle->cf_mutex);
|
err = uv_mutex_init(&handle->cf_mutex);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "idna.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stddef.h> /* NULL */
|
#include <stddef.h> /* NULL */
|
||||||
@@ -141,15 +142,34 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
const char* hostname,
|
const char* hostname,
|
||||||
const char* service,
|
const char* service,
|
||||||
const struct addrinfo* hints) {
|
const struct addrinfo* hints) {
|
||||||
|
char hostname_ascii[256];
|
||||||
size_t hostname_len;
|
size_t hostname_len;
|
||||||
size_t service_len;
|
size_t service_len;
|
||||||
size_t hints_len;
|
size_t hints_len;
|
||||||
size_t len;
|
size_t len;
|
||||||
char* buf;
|
char* buf;
|
||||||
|
long rc;
|
||||||
|
|
||||||
if (req == NULL || (hostname == NULL && service == NULL))
|
if (req == NULL || (hostname == NULL && service == NULL))
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
/* FIXME(bnoordhuis) IDNA does not seem to work z/OS,
|
||||||
|
* probably because it uses EBCDIC rather than ASCII.
|
||||||
|
*/
|
||||||
|
#ifdef __MVS__
|
||||||
|
(void) &hostname_ascii;
|
||||||
|
#else
|
||||||
|
if (hostname != NULL) {
|
||||||
|
rc = uv__idna_toascii(hostname,
|
||||||
|
hostname + strlen(hostname),
|
||||||
|
hostname_ascii,
|
||||||
|
hostname_ascii + sizeof(hostname_ascii));
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
hostname = hostname_ascii;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
hostname_len = hostname ? strlen(hostname) + 1 : 0;
|
hostname_len = hostname ? strlen(hostname) + 1 : 0;
|
||||||
service_len = service ? strlen(service) + 1 : 0;
|
service_len = service ? strlen(service) + 1 : 0;
|
||||||
hints_len = hints ? sizeof(*hints) : 0;
|
hints_len = hints ? sizeof(*hints) : 0;
|
||||||
@@ -186,6 +206,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
if (cb) {
|
if (cb) {
|
||||||
uv__work_submit(loop,
|
uv__work_submit(loop,
|
||||||
&req->work_req,
|
&req->work_req,
|
||||||
|
UV__WORK_SLOW_IO,
|
||||||
uv__getaddrinfo_work,
|
uv__getaddrinfo_work,
|
||||||
uv__getaddrinfo_done);
|
uv__getaddrinfo_done);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ int uv_getnameinfo(uv_loop_t* loop,
|
|||||||
if (getnameinfo_cb) {
|
if (getnameinfo_cb) {
|
||||||
uv__work_submit(loop,
|
uv__work_submit(loop,
|
||||||
&req->work_req,
|
&req->work_req,
|
||||||
|
UV__WORK_SLOW_IO,
|
||||||
uv__getnameinfo_work,
|
uv__getnameinfo_work,
|
||||||
uv__getnameinfo_done);
|
uv__getnameinfo_done);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ void uv_loadavg(double avg[3]) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_resident_set_memory(size_t* rss) {
|
int uv_resident_set_memory(size_t* rss) {
|
||||||
return UV_ENOSYS;
|
*rss = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -137,26 +137,6 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
|
|||||||
|
|
||||||
typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
|
typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
|
||||||
|
|
||||||
/* handle flags */
|
|
||||||
enum {
|
|
||||||
UV_CLOSING = 0x01, /* uv_close() called but not finished. */
|
|
||||||
UV_CLOSED = 0x02, /* close(2) finished. */
|
|
||||||
UV_STREAM_READING = 0x04, /* uv_read_start() called. */
|
|
||||||
UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */
|
|
||||||
UV_STREAM_SHUT = 0x10, /* Write side closed. */
|
|
||||||
UV_STREAM_READABLE = 0x20, /* The stream is readable */
|
|
||||||
UV_STREAM_WRITABLE = 0x40, /* The stream is writable */
|
|
||||||
UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */
|
|
||||||
UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */
|
|
||||||
UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */
|
|
||||||
UV_TCP_NODELAY = 0x400, /* Disable Nagle. */
|
|
||||||
UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */
|
|
||||||
UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */
|
|
||||||
UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */
|
|
||||||
UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */
|
|
||||||
UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* loop flags */
|
/* loop flags */
|
||||||
enum {
|
enum {
|
||||||
UV_LOOP_BLOCK_SIGPROF = 1
|
UV_LOOP_BLOCK_SIGPROF = 1
|
||||||
@@ -215,7 +195,6 @@ int uv__nonblock_fcntl(int fd, int set);
|
|||||||
int uv__close(int fd); /* preserves errno */
|
int uv__close(int fd); /* preserves errno */
|
||||||
int uv__close_nocheckstdio(int fd);
|
int uv__close_nocheckstdio(int fd);
|
||||||
int uv__socket(int domain, int type, int protocol);
|
int uv__socket(int domain, int type, int protocol);
|
||||||
int uv__dup(int fd);
|
|
||||||
ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
|
ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
|
||||||
void uv__make_close_pending(uv_handle_t* handle);
|
void uv__make_close_pending(uv_handle_t* handle);
|
||||||
int uv__getiovmax(void);
|
int uv__getiovmax(void);
|
||||||
@@ -229,6 +208,7 @@ int uv__io_active(const uv__io_t* w, unsigned int events);
|
|||||||
int uv__io_check_fd(uv_loop_t* loop, int fd);
|
int uv__io_check_fd(uv_loop_t* loop, int fd);
|
||||||
void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
|
void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
|
||||||
int uv__io_fork(uv_loop_t* loop);
|
int uv__io_fork(uv_loop_t* loop);
|
||||||
|
int uv__fd_exists(uv_loop_t* loop, int fd);
|
||||||
|
|
||||||
/* async */
|
/* async */
|
||||||
void uv__async_stop(uv_loop_t* loop);
|
void uv__async_stop(uv_loop_t* loop);
|
||||||
@@ -261,10 +241,6 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay);
|
|||||||
/* pipe */
|
/* pipe */
|
||||||
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
||||||
|
|
||||||
/* timer */
|
|
||||||
void uv__run_timers(uv_loop_t* loop);
|
|
||||||
int uv__next_timeout(const uv_loop_t* loop);
|
|
||||||
|
|
||||||
/* signal */
|
/* signal */
|
||||||
void uv__signal_close(uv_signal_t* handle);
|
void uv__signal_close(uv_signal_t* handle);
|
||||||
void uv__signal_global_once_init(void);
|
void uv__signal_global_once_init(void);
|
||||||
@@ -289,7 +265,6 @@ void uv__prepare_close(uv_prepare_t* handle);
|
|||||||
void uv__process_close(uv_process_t* handle);
|
void uv__process_close(uv_process_t* handle);
|
||||||
void uv__stream_close(uv_stream_t* handle);
|
void uv__stream_close(uv_stream_t* handle);
|
||||||
void uv__tcp_close(uv_tcp_t* handle);
|
void uv__tcp_close(uv_tcp_t* handle);
|
||||||
void uv__timer_close(uv_timer_t* handle);
|
|
||||||
void uv__udp_close(uv_udp_t* handle);
|
void uv__udp_close(uv_udp_t* handle);
|
||||||
void uv__udp_finish_close(uv_udp_t* handle);
|
void uv__udp_finish_close(uv_udp_t* handle);
|
||||||
uv_handle_type uv__handle_type(int fd);
|
uv_handle_type uv__handle_type(int fd);
|
||||||
@@ -319,24 +294,6 @@ int uv__fsevents_init(uv_fs_event_t* handle);
|
|||||||
int uv__fsevents_close(uv_fs_event_t* handle);
|
int uv__fsevents_close(uv_fs_event_t* handle);
|
||||||
void uv__fsevents_loop_delete(uv_loop_t* loop);
|
void uv__fsevents_loop_delete(uv_loop_t* loop);
|
||||||
|
|
||||||
/* OSX < 10.7 has no file events, polyfill them */
|
|
||||||
#ifndef MAC_OS_X_VERSION_10_7
|
|
||||||
|
|
||||||
static const int kFSEventStreamCreateFlagFileEvents = 0x00000010;
|
|
||||||
static const int kFSEventStreamEventFlagItemCreated = 0x00000100;
|
|
||||||
static const int kFSEventStreamEventFlagItemRemoved = 0x00000200;
|
|
||||||
static const int kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400;
|
|
||||||
static const int kFSEventStreamEventFlagItemRenamed = 0x00000800;
|
|
||||||
static const int kFSEventStreamEventFlagItemModified = 0x00001000;
|
|
||||||
static const int kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000;
|
|
||||||
static const int kFSEventStreamEventFlagItemChangeOwner = 0x00004000;
|
|
||||||
static const int kFSEventStreamEventFlagItemXattrMod = 0x00008000;
|
|
||||||
static const int kFSEventStreamEventFlagItemIsFile = 0x00010000;
|
|
||||||
static const int kFSEventStreamEventFlagItemIsDir = 0x00020000;
|
|
||||||
static const int kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
|
|
||||||
|
|
||||||
#endif /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 */
|
|
||||||
|
|
||||||
#endif /* defined(__APPLE__) */
|
#endif /* defined(__APPLE__) */
|
||||||
|
|
||||||
UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
|
UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
|
||||||
|
|||||||
@@ -261,8 +261,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
w = loop->watchers[fd];
|
w = loop->watchers[fd];
|
||||||
|
|
||||||
if (w == NULL) {
|
if (w == NULL) {
|
||||||
/* File descriptor that we've stopped watching, disarm it. */
|
/* File descriptor that we've stopped watching, disarm it.
|
||||||
/* TODO batch up */
|
* TODO: batch up. */
|
||||||
struct kevent events[1];
|
struct kevent events[1];
|
||||||
|
|
||||||
EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
|
EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
|
||||||
@@ -452,49 +452,48 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
uv_fs_event_cb cb,
|
uv_fs_event_cb cb,
|
||||||
const char* path,
|
const char* path,
|
||||||
unsigned int flags) {
|
unsigned int flags) {
|
||||||
#if defined(__APPLE__)
|
|
||||||
struct stat statbuf;
|
|
||||||
#endif /* defined(__APPLE__) */
|
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (uv__is_active(handle))
|
if (uv__is_active(handle))
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
/* TODO open asynchronously - but how do we report back errors? */
|
|
||||||
fd = open(path, O_RDONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
return UV__ERR(errno);
|
|
||||||
|
|
||||||
uv__handle_start(handle);
|
|
||||||
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
|
|
||||||
handle->path = uv__strdup(path);
|
|
||||||
handle->cb = cb;
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
if (uv__has_forked_with_cfrunloop)
|
|
||||||
goto fallback;
|
|
||||||
|
|
||||||
/* Nullify field to perform checks later */
|
/* Nullify field to perform checks later */
|
||||||
handle->cf_cb = NULL;
|
handle->cf_cb = NULL;
|
||||||
handle->realpath = NULL;
|
handle->realpath = NULL;
|
||||||
handle->realpath_len = 0;
|
handle->realpath_len = 0;
|
||||||
handle->cf_flags = flags;
|
handle->cf_flags = flags;
|
||||||
|
|
||||||
if (fstat(fd, &statbuf))
|
if (!uv__has_forked_with_cfrunloop) {
|
||||||
goto fallback;
|
int r;
|
||||||
/* FSEvents works only with directories */
|
/* The fallback fd is not used */
|
||||||
if (!(statbuf.st_mode & S_IFDIR))
|
handle->event_watcher.fd = -1;
|
||||||
goto fallback;
|
handle->path = uv__strdup(path);
|
||||||
|
if (handle->path == NULL)
|
||||||
/* The fallback fd is no longer needed */
|
return UV_ENOMEM;
|
||||||
uv__close(fd);
|
handle->cb = cb;
|
||||||
handle->event_watcher.fd = -1;
|
r = uv__fsevents_init(handle);
|
||||||
|
if (r == 0) {
|
||||||
return uv__fsevents_init(handle);
|
uv__handle_start(handle);
|
||||||
|
} else {
|
||||||
fallback:
|
uv__free(handle->path);
|
||||||
|
handle->path = NULL;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
#endif /* defined(__APPLE__) */
|
#endif /* defined(__APPLE__) */
|
||||||
|
|
||||||
|
/* TODO open asynchronously - but how do we report back errors? */
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
handle->path = uv__strdup(path);
|
||||||
|
if (handle->path == NULL)
|
||||||
|
return UV_ENOMEM;
|
||||||
|
handle->cb = cb;
|
||||||
|
uv__handle_start(handle);
|
||||||
|
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
|
||||||
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
|
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -502,29 +501,29 @@ fallback:
|
|||||||
|
|
||||||
|
|
||||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||||
|
int r;
|
||||||
|
r = 0;
|
||||||
|
|
||||||
if (!uv__is_active(handle))
|
if (!uv__is_active(handle))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uv__handle_stop(handle);
|
uv__handle_stop(handle);
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
if (uv__has_forked_with_cfrunloop || uv__fsevents_close(handle))
|
if (!uv__has_forked_with_cfrunloop)
|
||||||
#endif /* defined(__APPLE__) */
|
r = uv__fsevents_close(handle);
|
||||||
{
|
#endif
|
||||||
|
|
||||||
|
if (handle->event_watcher.fd != -1) {
|
||||||
uv__io_close(handle->loop, &handle->event_watcher);
|
uv__io_close(handle->loop, &handle->event_watcher);
|
||||||
|
uv__close(handle->event_watcher.fd);
|
||||||
|
handle->event_watcher.fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uv__free(handle->path);
|
uv__free(handle->path);
|
||||||
handle->path = NULL;
|
handle->path = NULL;
|
||||||
|
|
||||||
if (handle->event_watcher.fd != -1) {
|
return r;
|
||||||
/* When FSEvents is used, we don't use the event_watcher's fd under certain
|
|
||||||
* confitions. (see uv_fs_event_start) */
|
|
||||||
uv__close(handle->event_watcher.fd);
|
|
||||||
handle->event_watcher.fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their
|
/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their
|
||||||
* EPOLL* counterparts. We use the POLL* variants in this file because that
|
* EPOLL* counterparts. We use the POLL* variants in this file because that
|
||||||
* is what libuv uses elsewhere and it avoids a dependency on <sys/epoll.h>.
|
* is what libuv uses elsewhere.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_IFADDRS_H
|
#ifdef HAVE_IFADDRS_H
|
||||||
# if defined(__ANDROID__)
|
# if defined(__ANDROID__)
|
||||||
# include "android-ifaddrs.h"
|
# include "uv/android-ifaddrs.h"
|
||||||
# else
|
# else
|
||||||
# include <ifaddrs.h>
|
# include <ifaddrs.h>
|
||||||
# endif
|
# endif
|
||||||
@@ -84,13 +85,13 @@ static unsigned long read_cpufreq(unsigned int cpunum);
|
|||||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = uv__epoll_create1(UV__EPOLL_CLOEXEC);
|
fd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
|
|
||||||
/* epoll_create1() can fail either because it's not implemented (old kernel)
|
/* epoll_create1() can fail either because it's not implemented (old kernel)
|
||||||
* or because it doesn't understand the EPOLL_CLOEXEC flag.
|
* or because it doesn't understand the EPOLL_CLOEXEC flag.
|
||||||
*/
|
*/
|
||||||
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
|
if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
|
||||||
fd = uv__epoll_create(256);
|
fd = epoll_create(256);
|
||||||
|
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
uv__cloexec(fd, 1);
|
uv__cloexec(fd, 1);
|
||||||
@@ -134,20 +135,20 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
|
|||||||
|
|
||||||
|
|
||||||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
||||||
struct uv__epoll_event* events;
|
struct epoll_event* events;
|
||||||
struct uv__epoll_event dummy;
|
struct epoll_event dummy;
|
||||||
uintptr_t i;
|
uintptr_t i;
|
||||||
uintptr_t nfds;
|
uintptr_t nfds;
|
||||||
|
|
||||||
assert(loop->watchers != NULL);
|
assert(loop->watchers != NULL);
|
||||||
|
|
||||||
events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers];
|
events = (struct epoll_event*) loop->watchers[loop->nwatchers];
|
||||||
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
|
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
|
||||||
if (events != NULL)
|
if (events != NULL)
|
||||||
/* Invalidate events with same file descriptor */
|
/* Invalidate events with same file descriptor */
|
||||||
for (i = 0; i < nfds; i++)
|
for (i = 0; i < nfds; i++)
|
||||||
if ((int) events[i].data == fd)
|
if (events[i].data.fd == fd)
|
||||||
events[i].data = -1;
|
events[i].data.fd = -1;
|
||||||
|
|
||||||
/* Remove the file descriptor from the epoll.
|
/* Remove the file descriptor from the epoll.
|
||||||
* This avoids a problem where the same file description remains open
|
* This avoids a problem where the same file description remains open
|
||||||
@@ -160,25 +161,26 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
|||||||
* has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
|
* has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
|
||||||
*/
|
*/
|
||||||
memset(&dummy, 0, sizeof(dummy));
|
memset(&dummy, 0, sizeof(dummy));
|
||||||
uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy);
|
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||||
struct uv__epoll_event e;
|
struct epoll_event e;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
memset(&e, 0, sizeof(e));
|
||||||
e.events = POLLIN;
|
e.events = POLLIN;
|
||||||
e.data = -1;
|
e.data.fd = -1;
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
|
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
|
||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
rc = UV__ERR(errno);
|
rc = UV__ERR(errno);
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
|
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -195,16 +197,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
* that being the largest value I have seen in the wild (and only once.)
|
* that being the largest value I have seen in the wild (and only once.)
|
||||||
*/
|
*/
|
||||||
static const int max_safe_timeout = 1789569;
|
static const int max_safe_timeout = 1789569;
|
||||||
static int no_epoll_pwait;
|
struct epoll_event events[1024];
|
||||||
static int no_epoll_wait;
|
struct epoll_event* pe;
|
||||||
struct uv__epoll_event events[1024];
|
struct epoll_event e;
|
||||||
struct uv__epoll_event* pe;
|
|
||||||
struct uv__epoll_event e;
|
|
||||||
int real_timeout;
|
int real_timeout;
|
||||||
QUEUE* q;
|
QUEUE* q;
|
||||||
uv__io_t* w;
|
uv__io_t* w;
|
||||||
sigset_t sigset;
|
sigset_t sigset;
|
||||||
uint64_t sigmask;
|
sigset_t* psigset;
|
||||||
uint64_t base;
|
uint64_t base;
|
||||||
int have_signals;
|
int have_signals;
|
||||||
int nevents;
|
int nevents;
|
||||||
@@ -219,6 +219,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(&e, 0, sizeof(e));
|
||||||
|
|
||||||
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
||||||
q = QUEUE_HEAD(&loop->watcher_queue);
|
q = QUEUE_HEAD(&loop->watcher_queue);
|
||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
@@ -230,35 +232,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
assert(w->fd < (int) loop->nwatchers);
|
assert(w->fd < (int) loop->nwatchers);
|
||||||
|
|
||||||
e.events = w->pevents;
|
e.events = w->pevents;
|
||||||
e.data = w->fd;
|
e.data.fd = w->fd;
|
||||||
|
|
||||||
if (w->events == 0)
|
if (w->events == 0)
|
||||||
op = UV__EPOLL_CTL_ADD;
|
op = EPOLL_CTL_ADD;
|
||||||
else
|
else
|
||||||
op = UV__EPOLL_CTL_MOD;
|
op = EPOLL_CTL_MOD;
|
||||||
|
|
||||||
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
||||||
* events, skip the syscall and squelch the events after epoll_wait().
|
* events, skip the syscall and squelch the events after epoll_wait().
|
||||||
*/
|
*/
|
||||||
if (uv__epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
|
if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
|
||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
assert(op == UV__EPOLL_CTL_ADD);
|
assert(op == EPOLL_CTL_ADD);
|
||||||
|
|
||||||
/* We've reactivated a file descriptor that's been watched before. */
|
/* We've reactivated a file descriptor that's been watched before. */
|
||||||
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_MOD, w->fd, &e))
|
if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
w->events = w->pevents;
|
w->events = w->pevents;
|
||||||
}
|
}
|
||||||
|
|
||||||
sigmask = 0;
|
psigset = NULL;
|
||||||
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
|
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
|
||||||
sigemptyset(&sigset);
|
sigemptyset(&sigset);
|
||||||
sigaddset(&sigset, SIGPROF);
|
sigaddset(&sigset, SIGPROF);
|
||||||
sigmask |= 1 << (SIGPROF - 1);
|
psigset = &sigset;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(timeout >= -1);
|
assert(timeout >= -1);
|
||||||
@@ -273,30 +275,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
|
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
|
||||||
timeout = max_safe_timeout;
|
timeout = max_safe_timeout;
|
||||||
|
|
||||||
if (sigmask != 0 && no_epoll_pwait != 0)
|
nfds = epoll_pwait(loop->backend_fd,
|
||||||
if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
|
events,
|
||||||
abort();
|
ARRAY_SIZE(events),
|
||||||
|
timeout,
|
||||||
if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
|
psigset);
|
||||||
nfds = uv__epoll_pwait(loop->backend_fd,
|
|
||||||
events,
|
|
||||||
ARRAY_SIZE(events),
|
|
||||||
timeout,
|
|
||||||
sigmask);
|
|
||||||
if (nfds == -1 && errno == ENOSYS)
|
|
||||||
no_epoll_pwait = 1;
|
|
||||||
} else {
|
|
||||||
nfds = uv__epoll_wait(loop->backend_fd,
|
|
||||||
events,
|
|
||||||
ARRAY_SIZE(events),
|
|
||||||
timeout);
|
|
||||||
if (nfds == -1 && errno == ENOSYS)
|
|
||||||
no_epoll_wait = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sigmask != 0 && no_epoll_pwait != 0)
|
|
||||||
if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
|
|
||||||
abort();
|
|
||||||
|
|
||||||
/* Update loop->time unconditionally. It's tempting to skip the update when
|
/* Update loop->time unconditionally. It's tempting to skip the update when
|
||||||
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
|
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
|
||||||
@@ -317,12 +300,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nfds == -1) {
|
if (nfds == -1) {
|
||||||
if (errno == ENOSYS) {
|
|
||||||
/* epoll_wait() or epoll_pwait() failed, try the other system call. */
|
|
||||||
assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
@@ -344,7 +321,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
||||||
for (i = 0; i < nfds; i++) {
|
for (i = 0; i < nfds; i++) {
|
||||||
pe = events + i;
|
pe = events + i;
|
||||||
fd = pe->data;
|
fd = pe->data.fd;
|
||||||
|
|
||||||
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
@@ -361,7 +338,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
* Ignore all errors because we may be racing with another thread
|
* Ignore all errors because we may be racing with another thread
|
||||||
* when the file descriptor is closed.
|
* when the file descriptor is closed.
|
||||||
*/
|
*/
|
||||||
uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe);
|
epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +365,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
* free when we switch over to edge-triggered I/O.
|
* free when we switch over to edge-triggered I/O.
|
||||||
*/
|
*/
|
||||||
if (pe->events == POLLERR || pe->events == POLLHUP)
|
if (pe->events == POLLERR || pe->events == POLLHUP)
|
||||||
pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI);
|
pe->events |=
|
||||||
|
w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||||
|
|
||||||
if (pe->events != 0) {
|
if (pe->events != 0) {
|
||||||
/* Run signal watchers last. This also affects child process watchers
|
/* Run signal watchers last. This also affects child process watchers
|
||||||
@@ -851,9 +829,10 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
|||||||
return !exclude_type;
|
return !exclude_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uv_interface_addresses(uv_interface_address_t** addresses,
|
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||||
int* count) {
|
|
||||||
#ifndef HAVE_IFADDRS_H
|
#ifndef HAVE_IFADDRS_H
|
||||||
|
*count = 0;
|
||||||
|
*addresses = NULL;
|
||||||
return UV_ENOSYS;
|
return UV_ENOSYS;
|
||||||
#else
|
#else
|
||||||
struct ifaddrs *addrs, *ent;
|
struct ifaddrs *addrs, *ent;
|
||||||
@@ -861,12 +840,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
|||||||
int i;
|
int i;
|
||||||
struct sockaddr_ll *sll;
|
struct sockaddr_ll *sll;
|
||||||
|
|
||||||
if (getifaddrs(&addrs))
|
|
||||||
return UV__ERR(errno);
|
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
*addresses = NULL;
|
*addresses = NULL;
|
||||||
|
|
||||||
|
if (getifaddrs(&addrs))
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
/* Count the number of interfaces */
|
/* Count the number of interfaces */
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||||
@@ -875,8 +854,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
|||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*count == 0)
|
if (*count == 0) {
|
||||||
|
freeifaddrs(addrs);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*addresses = uv__malloc(*count * sizeof(**addresses));
|
*addresses = uv__malloc(*count * sizeof(**addresses));
|
||||||
if (!(*addresses)) {
|
if (!(*addresses)) {
|
||||||
@@ -920,6 +901,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
|||||||
if (strcmp(address->name, ent->ifa_name) == 0) {
|
if (strcmp(address->name, ent->ifa_name) == 0) {
|
||||||
sll = (struct sockaddr_ll*)ent->ifa_addr;
|
sll = (struct sockaddr_ll*)ent->ifa_addr;
|
||||||
memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
|
memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
|
||||||
|
} else {
|
||||||
|
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||||
}
|
}
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "tree.h"
|
#include "uv/tree.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -278,6 +278,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
const char* path,
|
const char* path,
|
||||||
unsigned int flags) {
|
unsigned int flags) {
|
||||||
struct watcher_list* w;
|
struct watcher_list* w;
|
||||||
|
size_t len;
|
||||||
int events;
|
int events;
|
||||||
int err;
|
int err;
|
||||||
int wd;
|
int wd;
|
||||||
@@ -306,12 +307,13 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
if (w)
|
if (w)
|
||||||
goto no_insert;
|
goto no_insert;
|
||||||
|
|
||||||
w = uv__malloc(sizeof(*w) + strlen(path) + 1);
|
len = strlen(path) + 1;
|
||||||
|
w = uv__malloc(sizeof(*w) + len);
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
|
|
||||||
w->wd = wd;
|
w->wd = wd;
|
||||||
w->path = strcpy((char*)(w + 1), path);
|
w->path = memcpy(w + 1, path, len);
|
||||||
QUEUE_INIT(&w->watchers);
|
QUEUE_INIT(&w->watchers);
|
||||||
w->iterating = 0;
|
w->iterating = 0;
|
||||||
RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w);
|
RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w);
|
||||||
|
|||||||
@@ -77,56 +77,6 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif /* __NR_eventfd2 */
|
#endif /* __NR_eventfd2 */
|
||||||
|
|
||||||
#ifndef __NR_epoll_create
|
|
||||||
# if defined(__x86_64__)
|
|
||||||
# define __NR_epoll_create 213
|
|
||||||
# elif defined(__i386__)
|
|
||||||
# define __NR_epoll_create 254
|
|
||||||
# elif defined(__arm__)
|
|
||||||
# define __NR_epoll_create (UV_SYSCALL_BASE + 250)
|
|
||||||
# endif
|
|
||||||
#endif /* __NR_epoll_create */
|
|
||||||
|
|
||||||
#ifndef __NR_epoll_create1
|
|
||||||
# if defined(__x86_64__)
|
|
||||||
# define __NR_epoll_create1 291
|
|
||||||
# elif defined(__i386__)
|
|
||||||
# define __NR_epoll_create1 329
|
|
||||||
# elif defined(__arm__)
|
|
||||||
# define __NR_epoll_create1 (UV_SYSCALL_BASE + 357)
|
|
||||||
# endif
|
|
||||||
#endif /* __NR_epoll_create1 */
|
|
||||||
|
|
||||||
#ifndef __NR_epoll_ctl
|
|
||||||
# if defined(__x86_64__)
|
|
||||||
# define __NR_epoll_ctl 233 /* used to be 214 */
|
|
||||||
# elif defined(__i386__)
|
|
||||||
# define __NR_epoll_ctl 255
|
|
||||||
# elif defined(__arm__)
|
|
||||||
# define __NR_epoll_ctl (UV_SYSCALL_BASE + 251)
|
|
||||||
# endif
|
|
||||||
#endif /* __NR_epoll_ctl */
|
|
||||||
|
|
||||||
#ifndef __NR_epoll_wait
|
|
||||||
# if defined(__x86_64__)
|
|
||||||
# define __NR_epoll_wait 232 /* used to be 215 */
|
|
||||||
# elif defined(__i386__)
|
|
||||||
# define __NR_epoll_wait 256
|
|
||||||
# elif defined(__arm__)
|
|
||||||
# define __NR_epoll_wait (UV_SYSCALL_BASE + 252)
|
|
||||||
# endif
|
|
||||||
#endif /* __NR_epoll_wait */
|
|
||||||
|
|
||||||
#ifndef __NR_epoll_pwait
|
|
||||||
# if defined(__x86_64__)
|
|
||||||
# define __NR_epoll_pwait 281
|
|
||||||
# elif defined(__i386__)
|
|
||||||
# define __NR_epoll_pwait 319
|
|
||||||
# elif defined(__arm__)
|
|
||||||
# define __NR_epoll_pwait (UV_SYSCALL_BASE + 346)
|
|
||||||
# endif
|
|
||||||
#endif /* __NR_epoll_pwait */
|
|
||||||
|
|
||||||
#ifndef __NR_inotify_init
|
#ifndef __NR_inotify_init
|
||||||
# if defined(__x86_64__)
|
# if defined(__x86_64__)
|
||||||
# define __NR_inotify_init 253
|
# define __NR_inotify_init 253
|
||||||
@@ -285,76 +235,6 @@ int uv__eventfd2(unsigned int count, int flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv__epoll_create(int size) {
|
|
||||||
#if defined(__NR_epoll_create)
|
|
||||||
return syscall(__NR_epoll_create, size);
|
|
||||||
#else
|
|
||||||
return errno = ENOSYS, -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__epoll_create1(int flags) {
|
|
||||||
#if defined(__NR_epoll_create1)
|
|
||||||
return syscall(__NR_epoll_create1, flags);
|
|
||||||
#else
|
|
||||||
return errno = ENOSYS, -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event* events) {
|
|
||||||
#if defined(__NR_epoll_ctl)
|
|
||||||
return syscall(__NR_epoll_ctl, epfd, op, fd, events);
|
|
||||||
#else
|
|
||||||
return errno = ENOSYS, -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__epoll_wait(int epfd,
|
|
||||||
struct uv__epoll_event* events,
|
|
||||||
int nevents,
|
|
||||||
int timeout) {
|
|
||||||
#if defined(__NR_epoll_wait)
|
|
||||||
int result;
|
|
||||||
result = syscall(__NR_epoll_wait, epfd, events, nevents, timeout);
|
|
||||||
#if MSAN_ACTIVE
|
|
||||||
if (result > 0)
|
|
||||||
__msan_unpoison(events, sizeof(events[0]) * result);
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
#else
|
|
||||||
return errno = ENOSYS, -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__epoll_pwait(int epfd,
|
|
||||||
struct uv__epoll_event* events,
|
|
||||||
int nevents,
|
|
||||||
int timeout,
|
|
||||||
uint64_t sigmask) {
|
|
||||||
#if defined(__NR_epoll_pwait)
|
|
||||||
int result;
|
|
||||||
result = syscall(__NR_epoll_pwait,
|
|
||||||
epfd,
|
|
||||||
events,
|
|
||||||
nevents,
|
|
||||||
timeout,
|
|
||||||
&sigmask,
|
|
||||||
sizeof(sigmask));
|
|
||||||
#if MSAN_ACTIVE
|
|
||||||
if (result > 0)
|
|
||||||
__msan_unpoison(events, sizeof(events[0]) * result);
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
#else
|
|
||||||
return errno = ENOSYS, -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__inotify_init(void) {
|
int uv__inotify_init(void) {
|
||||||
#if defined(__NR_inotify_init)
|
#if defined(__NR_inotify_init)
|
||||||
return syscall(__NR_inotify_init);
|
return syscall(__NR_inotify_init);
|
||||||
@@ -431,19 +311,6 @@ int uv__recvmmsg(int fd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv__utimesat(int dirfd,
|
|
||||||
const char* path,
|
|
||||||
const struct timespec times[2],
|
|
||||||
int flags)
|
|
||||||
{
|
|
||||||
#if defined(__NR_utimensat)
|
|
||||||
return syscall(__NR_utimensat, dirfd, path, times, flags);
|
|
||||||
#else
|
|
||||||
return errno = ENOSYS, -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
|
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
|
||||||
#if defined(__NR_preadv)
|
#if defined(__NR_preadv)
|
||||||
return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
|
return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
|
||||||
|
|||||||
@@ -66,12 +66,6 @@
|
|||||||
# define UV__SOCK_NONBLOCK UV__O_NONBLOCK
|
# define UV__SOCK_NONBLOCK UV__O_NONBLOCK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* epoll flags */
|
|
||||||
#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
|
|
||||||
#define UV__EPOLL_CTL_ADD 1
|
|
||||||
#define UV__EPOLL_CTL_DEL 2
|
|
||||||
#define UV__EPOLL_CTL_MOD 3
|
|
||||||
|
|
||||||
/* inotify flags */
|
/* inotify flags */
|
||||||
#define UV__IN_ACCESS 0x001
|
#define UV__IN_ACCESS 0x001
|
||||||
#define UV__IN_MODIFY 0x002
|
#define UV__IN_MODIFY 0x002
|
||||||
@@ -86,18 +80,6 @@
|
|||||||
#define UV__IN_DELETE_SELF 0x400
|
#define UV__IN_DELETE_SELF 0x400
|
||||||
#define UV__IN_MOVE_SELF 0x800
|
#define UV__IN_MOVE_SELF 0x800
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
|
||||||
struct uv__epoll_event {
|
|
||||||
uint32_t events;
|
|
||||||
uint64_t data;
|
|
||||||
} __attribute__((packed));
|
|
||||||
#else
|
|
||||||
struct uv__epoll_event {
|
|
||||||
uint32_t events;
|
|
||||||
uint64_t data;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct uv__inotify_event {
|
struct uv__inotify_event {
|
||||||
int32_t wd;
|
int32_t wd;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
@@ -113,18 +95,6 @@ struct uv__mmsghdr {
|
|||||||
|
|
||||||
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
|
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
|
||||||
int uv__eventfd(unsigned int count);
|
int uv__eventfd(unsigned int count);
|
||||||
int uv__epoll_create(int size);
|
|
||||||
int uv__epoll_create1(int flags);
|
|
||||||
int uv__epoll_ctl(int epfd, int op, int fd, struct uv__epoll_event *ev);
|
|
||||||
int uv__epoll_wait(int epfd,
|
|
||||||
struct uv__epoll_event* events,
|
|
||||||
int nevents,
|
|
||||||
int timeout);
|
|
||||||
int uv__epoll_pwait(int epfd,
|
|
||||||
struct uv__epoll_event* events,
|
|
||||||
int nevents,
|
|
||||||
int timeout,
|
|
||||||
uint64_t sigmask);
|
|
||||||
int uv__eventfd2(unsigned int count, int flags);
|
int uv__eventfd2(unsigned int count, int flags);
|
||||||
int uv__inotify_init(void);
|
int uv__inotify_init(void);
|
||||||
int uv__inotify_init1(int flags);
|
int uv__inotify_init1(int flags);
|
||||||
@@ -140,10 +110,6 @@ int uv__sendmmsg(int fd,
|
|||||||
struct uv__mmsghdr* mmsg,
|
struct uv__mmsghdr* mmsg,
|
||||||
unsigned int vlen,
|
unsigned int vlen,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
int uv__utimesat(int dirfd,
|
|
||||||
const char* path,
|
|
||||||
const struct timespec times[2],
|
|
||||||
int flags);
|
|
||||||
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
|
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
|
||||||
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
|
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
|
||||||
int uv__dup3(int oldfd, int newfd, int flags);
|
int uv__dup3(int oldfd, int newfd, int flags);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "tree.h"
|
#include "uv/tree.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "heap-inl.h"
|
#include "heap-inl.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -74,7 +74,7 @@ int uv_loop_init(uv_loop_t* loop) {
|
|||||||
goto fail_signal_init;
|
goto fail_signal_init;
|
||||||
|
|
||||||
uv__handle_unref(&loop->child_watcher);
|
uv__handle_unref(&loop->child_watcher);
|
||||||
loop->child_watcher.flags |= UV__HANDLE_INTERNAL;
|
loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
|
||||||
QUEUE_INIT(&loop->process_handles);
|
QUEUE_INIT(&loop->process_handles);
|
||||||
|
|
||||||
err = uv_rwlock_init(&loop->cloexec_lock);
|
err = uv_rwlock_init(&loop->cloexec_lock);
|
||||||
@@ -90,7 +90,7 @@ int uv_loop_init(uv_loop_t* loop) {
|
|||||||
goto fail_async_init;
|
goto fail_async_init;
|
||||||
|
|
||||||
uv__handle_unref(&loop->wq_async);
|
uv__handle_unref(&loop->wq_async);
|
||||||
loop->wq_async.flags |= UV__HANDLE_INTERNAL;
|
loop->wq_async.flags |= UV_HANDLE_INTERNAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -40,15 +40,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static uv_mutex_t process_title_mutex;
|
|
||||||
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
|
||||||
static char *process_title;
|
|
||||||
|
|
||||||
|
|
||||||
static void init_process_title_mutex_once(void) {
|
|
||||||
uv_mutex_init(&process_title_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||||
return uv__kqueue_init(loop);
|
return uv__kqueue_init(loop);
|
||||||
@@ -96,7 +87,8 @@ int uv_exepath(char* buffer, size_t* size) {
|
|||||||
/* Copy string from the intermediate buffer to outer one with appropriate
|
/* Copy string from the intermediate buffer to outer one with appropriate
|
||||||
* length.
|
* length.
|
||||||
*/
|
*/
|
||||||
strlcpy(buffer, int_buf, *size);
|
/* TODO(bnoordhuis) Check uv__strscpy() return value. */
|
||||||
|
uv__strscpy(buffer, int_buf, *size);
|
||||||
|
|
||||||
/* Set new size. */
|
/* Set new size. */
|
||||||
*size = strlen(buffer);
|
*size = strlen(buffer);
|
||||||
@@ -134,65 +126,6 @@ uint64_t uv_get_total_memory(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char** uv_setup_args(int argc, char** argv) {
|
|
||||||
process_title = argc ? uv__strdup(argv[0]) : NULL;
|
|
||||||
return argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_set_process_title(const char* title) {
|
|
||||||
char* new_title;
|
|
||||||
|
|
||||||
new_title = uv__strdup(title);
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
||||||
uv_mutex_lock(&process_title_mutex);
|
|
||||||
|
|
||||||
if (process_title == NULL) {
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
return UV_ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(process_title);
|
|
||||||
process_title = new_title;
|
|
||||||
setproctitle("%s", title);
|
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_get_process_title(char* buffer, size_t size) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (buffer == NULL || size == 0)
|
|
||||||
return UV_EINVAL;
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
||||||
uv_mutex_lock(&process_title_mutex);
|
|
||||||
|
|
||||||
if (process_title) {
|
|
||||||
len = strlen(process_title) + 1;
|
|
||||||
|
|
||||||
if (size < len) {
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
return UV_ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, process_title, len);
|
|
||||||
} else {
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
|
|
||||||
buffer[len] = '\0';
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_resident_set_memory(size_t* rss) {
|
int uv_resident_set_memory(size_t* rss) {
|
||||||
kvm_t *kd = NULL;
|
kvm_t *kd = NULL;
|
||||||
struct kinfo_proc2 *kinfo = NULL;
|
struct kinfo_proc2 *kinfo = NULL;
|
||||||
|
|||||||
@@ -36,16 +36,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
static uv_mutex_t process_title_mutex;
|
|
||||||
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
|
||||||
static char *process_title;
|
|
||||||
|
|
||||||
|
|
||||||
static void init_process_title_mutex_once(void) {
|
|
||||||
uv_mutex_init(&process_title_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||||
return uv__kqueue_init(loop);
|
return uv__kqueue_init(loop);
|
||||||
}
|
}
|
||||||
@@ -146,65 +136,6 @@ uint64_t uv_get_total_memory(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char** uv_setup_args(int argc, char** argv) {
|
|
||||||
process_title = argc ? uv__strdup(argv[0]) : NULL;
|
|
||||||
return argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_set_process_title(const char* title) {
|
|
||||||
char* new_title;
|
|
||||||
|
|
||||||
new_title = uv__strdup(title);
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
||||||
uv_mutex_lock(&process_title_mutex);
|
|
||||||
|
|
||||||
if (process_title == NULL) {
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
return UV_ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(process_title);
|
|
||||||
process_title = new_title;
|
|
||||||
setproctitle("%s", title);
|
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_get_process_title(char* buffer, size_t size) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (buffer == NULL || size == 0)
|
|
||||||
return UV_EINVAL;
|
|
||||||
|
|
||||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
|
||||||
uv_mutex_lock(&process_title_mutex);
|
|
||||||
|
|
||||||
if (process_title) {
|
|
||||||
len = strlen(process_title) + 1;
|
|
||||||
|
|
||||||
if (size < len) {
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
return UV_ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, process_title, len);
|
|
||||||
} else {
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv_mutex_unlock(&process_title_mutex);
|
|
||||||
|
|
||||||
buffer[len] = '\0';
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_resident_set_memory(size_t* rss) {
|
int uv_resident_set_memory(size_t* rss) {
|
||||||
struct kinfo_proc kinfo;
|
struct kinfo_proc kinfo;
|
||||||
size_t page_size = getpagesize();
|
size_t page_size = getpagesize();
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ static void init_message_queue(uv__os390_epoll* lst) {
|
|||||||
} msg;
|
} msg;
|
||||||
|
|
||||||
/* initialize message queue */
|
/* initialize message queue */
|
||||||
lst->msg_queue = msgget(IPC_PRIVATE, 0622 | IPC_CREAT);
|
lst->msg_queue = msgget(IPC_PRIVATE, 0600 | IPC_CREAT);
|
||||||
if (lst->msg_queue == -1)
|
if (lst->msg_queue == -1)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
@@ -255,12 +255,13 @@ int epoll_ctl(uv__os390_epoll* lst,
|
|||||||
lst->items[fd].events = event->events;
|
lst->items[fd].events = event->events;
|
||||||
lst->items[fd].revents = 0;
|
lst->items[fd].revents = 0;
|
||||||
} else if (op == EPOLL_CTL_MOD) {
|
} else if (op == EPOLL_CTL_MOD) {
|
||||||
if (fd >= lst->size || lst->items[fd].fd == -1) {
|
if (fd >= lst->size - 1 || lst->items[fd].fd == -1) {
|
||||||
uv_mutex_unlock(&global_epoll_lock);
|
uv_mutex_unlock(&global_epoll_lock);
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
lst->items[fd].events = event->events;
|
lst->items[fd].events = event->events;
|
||||||
|
lst->items[fd].revents = 0;
|
||||||
} else
|
} else
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
@@ -275,8 +276,9 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
|||||||
struct pollfd* pfds;
|
struct pollfd* pfds;
|
||||||
int pollret;
|
int pollret;
|
||||||
int reventcount;
|
int reventcount;
|
||||||
|
int nevents;
|
||||||
|
|
||||||
size = _SET_FDS_MSGS(size, 1, lst->size - 1);
|
_SET_FDS_MSGS(size, 1, lst->size - 1);
|
||||||
pfds = lst->items;
|
pfds = lst->items;
|
||||||
pollret = poll(pfds, size, timeout);
|
pollret = poll(pfds, size, timeout);
|
||||||
if (pollret <= 0)
|
if (pollret <= 0)
|
||||||
@@ -285,19 +287,28 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
|||||||
pollret = _NFDS(pollret) + _NMSGS(pollret);
|
pollret = _NFDS(pollret) + _NMSGS(pollret);
|
||||||
|
|
||||||
reventcount = 0;
|
reventcount = 0;
|
||||||
|
nevents = 0;
|
||||||
for (int i = 0;
|
for (int i = 0;
|
||||||
i < lst->size && i < maxevents && reventcount < pollret; ++i) {
|
i < lst->size && i < maxevents && reventcount < pollret; ++i) {
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
|
struct pollfd* pfd;
|
||||||
|
|
||||||
if (pfds[i].fd == -1 || pfds[i].revents == 0)
|
pfd = &pfds[i];
|
||||||
|
if (pfd->fd == -1 || pfd->revents == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev.fd = pfds[i].fd;
|
ev.fd = pfd->fd;
|
||||||
ev.events = pfds[i].revents;
|
ev.events = pfd->revents;
|
||||||
events[reventcount++] = ev;
|
if (pfd->revents & POLLIN && pfd->revents & POLLOUT)
|
||||||
|
reventcount += 2;
|
||||||
|
else if (pfd->revents & (POLLIN | POLLOUT))
|
||||||
|
++reventcount;
|
||||||
|
|
||||||
|
pfd->revents = 0;
|
||||||
|
events[nevents++] = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
return reventcount;
|
return nevents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -493,7 +504,7 @@ ssize_t os390_readlink(const char* path, char* buf, size_t len) {
|
|||||||
|
|
||||||
|
|
||||||
size_t strnlen(const char* str, size_t maxlen) {
|
size_t strnlen(const char* str, size_t maxlen) {
|
||||||
void* p = memchr(str, 0, maxlen);
|
char* p = memchr(str, 0, maxlen);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return maxlen;
|
return maxlen;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -36,10 +36,6 @@
|
|||||||
#define MAX_ITEMS_PER_EPOLL 1024
|
#define MAX_ITEMS_PER_EPOLL 1024
|
||||||
|
|
||||||
#define UV__O_CLOEXEC 0x80000
|
#define UV__O_CLOEXEC 0x80000
|
||||||
#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
|
|
||||||
#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD
|
|
||||||
#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL
|
|
||||||
#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD
|
|
||||||
|
|
||||||
struct epoll_event {
|
struct epoll_event {
|
||||||
int events;
|
int events;
|
||||||
|
|||||||
@@ -229,15 +229,15 @@ static int getexe(const int pid, char* buf, size_t len) {
|
|||||||
assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A');
|
assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A');
|
||||||
|
|
||||||
/* Get the offset from the lowest 3 bytes */
|
/* Get the offset from the lowest 3 bytes */
|
||||||
Output_path = (char*)(&Output_buf) +
|
Output_path = (struct Output_path_type*) ((char*) (&Output_buf) +
|
||||||
(Output_buf.Output_data.offsetPath & 0x00FFFFFF);
|
(Output_buf.Output_data.offsetPath & 0x00FFFFFF));
|
||||||
|
|
||||||
if (Output_path->len >= len) {
|
if (Output_path->len >= len) {
|
||||||
errno = ENOBUFS;
|
errno = ENOBUFS;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(buf, Output_path->path, len);
|
uv__strscpy(buf, Output_path->path, len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -357,13 +357,11 @@ uint64_t uv_get_total_memory(void) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_resident_set_memory(size_t* rss) {
|
int uv_resident_set_memory(size_t* rss) {
|
||||||
char* psa;
|
|
||||||
char* ascb;
|
char* ascb;
|
||||||
char* rax;
|
char* rax;
|
||||||
size_t nframes;
|
size_t nframes;
|
||||||
|
|
||||||
psa = PSA_PTR;
|
ascb = *(char* __ptr32 *)(PSA_PTR + PSAAOLD);
|
||||||
ascb = *(char* __ptr32 *)(psa + PSAAOLD);
|
|
||||||
rax = *(char* __ptr32 *)(ascb + ASCBRSME);
|
rax = *(char* __ptr32 *)(ascb + ASCBRSME);
|
||||||
nframes = *(unsigned int*)(rax + RAXFMCT);
|
nframes = *(unsigned int*)(rax + RAXFMCT);
|
||||||
|
|
||||||
@@ -512,7 +510,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
|
|||||||
/* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
|
/* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
|
||||||
|
|
||||||
address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
|
address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
|
||||||
|
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,12 +529,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
struct ifreq* p;
|
struct ifreq* p;
|
||||||
int count_v6;
|
int count_v6;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
*addresses = NULL;
|
||||||
|
|
||||||
/* get the ipv6 addresses first */
|
/* get the ipv6 addresses first */
|
||||||
uv_interface_address_t* addresses_v6;
|
uv_interface_address_t* addresses_v6;
|
||||||
uv__interface_addresses_v6(&addresses_v6, &count_v6);
|
uv__interface_addresses_v6(&addresses_v6, &count_v6);
|
||||||
|
|
||||||
/* now get the ipv4 addresses */
|
/* now get the ipv4 addresses */
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
/* Assume maximum buffer size allowable */
|
/* Assume maximum buffer size allowable */
|
||||||
maxsize = 16384;
|
maxsize = 16384;
|
||||||
@@ -578,6 +578,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*count == 0) {
|
||||||
|
uv__close(sockfd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Alloc the return interface structs */
|
/* Alloc the return interface structs */
|
||||||
*addresses = uv__malloc((*count + count_v6) *
|
*addresses = uv__malloc((*count + count_v6) *
|
||||||
sizeof(uv_interface_address_t));
|
sizeof(uv_interface_address_t));
|
||||||
@@ -624,6 +629,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
||||||
|
memset(address->phys_addr, 0, sizeof(address->phys_addr));
|
||||||
address++;
|
address++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,7 +668,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
|||||||
|
|
||||||
/* Remove the file descriptor from the epoll. */
|
/* Remove the file descriptor from the epoll. */
|
||||||
if (loop->ep != NULL)
|
if (loop->ep != NULL)
|
||||||
epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy);
|
epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -751,7 +757,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
|
|||||||
memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok,
|
memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok,
|
||||||
sizeof(handle->rfis_rftok));
|
sizeof(handle->rfis_rftok));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This call will take "/" as the path argument in case we
|
* This call will take "/" as the path argument in case we
|
||||||
* don't care to supply the correct path. The system will simply
|
* don't care to supply the correct path. The system will simply
|
||||||
* ignore it.
|
* ignore it.
|
||||||
@@ -838,9 +844,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
e.fd = w->fd;
|
e.fd = w->fd;
|
||||||
|
|
||||||
if (w->events == 0)
|
if (w->events == 0)
|
||||||
op = UV__EPOLL_CTL_ADD;
|
op = EPOLL_CTL_ADD;
|
||||||
else
|
else
|
||||||
op = UV__EPOLL_CTL_MOD;
|
op = EPOLL_CTL_MOD;
|
||||||
|
|
||||||
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
||||||
* events, skip the syscall and squelch the events after epoll_wait().
|
* events, skip the syscall and squelch the events after epoll_wait().
|
||||||
@@ -849,10 +855,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
if (errno != EEXIST)
|
if (errno != EEXIST)
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
assert(op == UV__EPOLL_CTL_ADD);
|
assert(op == EPOLL_CTL_ADD);
|
||||||
|
|
||||||
/* We've reactivated a file descriptor that's been watched before. */
|
/* We've reactivated a file descriptor that's been watched before. */
|
||||||
if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e))
|
if (epoll_ctl(loop->ep, EPOLL_CTL_MOD, w->fd, &e))
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,7 +940,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
|||||||
* Ignore all errors because we may be racing with another thread
|
* Ignore all errors because we may be racing with another thread
|
||||||
* when the file descriptor is closed.
|
* when the file descriptor is closed.
|
||||||
*/
|
*/
|
||||||
epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe);
|
epoll_ctl(loop->ep, EPOLL_CTL_DEL, fd, pe);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -987,7 +993,7 @@ void uv__set_process_title(const char* title) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int uv__io_fork(uv_loop_t* loop) {
|
int uv__io_fork(uv_loop_t* loop) {
|
||||||
/*
|
/*
|
||||||
Nullify the msg queue but don't close it because
|
Nullify the msg queue but don't close it because
|
||||||
it is still being used by the parent.
|
it is still being used by the parent.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
|||||||
sockfd = err;
|
sockfd = err;
|
||||||
|
|
||||||
memset(&saddr, 0, sizeof saddr);
|
memset(&saddr, 0, sizeof saddr);
|
||||||
strncpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path) - 1);
|
uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
|
||||||
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
|
|
||||||
saddr.sun_family = AF_UNIX;
|
saddr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
|
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
|
||||||
@@ -130,7 +129,20 @@ void uv__pipe_close(uv_pipe_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
|
int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
|
||||||
|
int flags;
|
||||||
|
int mode;
|
||||||
int err;
|
int err;
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
|
if (uv__fd_exists(handle->loop, fd))
|
||||||
|
return UV_EEXIST;
|
||||||
|
|
||||||
|
do
|
||||||
|
mode = fcntl(fd, F_GETFL);
|
||||||
|
while (mode == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (mode == -1)
|
||||||
|
return UV__ERR(errno); /* according to docs, must be EBADF */
|
||||||
|
|
||||||
err = uv__nonblock(fd, 1);
|
err = uv__nonblock(fd, 1);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -142,9 +154,13 @@ int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
|
|||||||
return err;
|
return err;
|
||||||
#endif /* defined(__APPLE__) */
|
#endif /* defined(__APPLE__) */
|
||||||
|
|
||||||
return uv__stream_open((uv_stream_t*)handle,
|
mode &= O_ACCMODE;
|
||||||
fd,
|
if (mode != O_WRONLY)
|
||||||
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
|
flags |= UV_HANDLE_READABLE;
|
||||||
|
if (mode != O_RDONLY)
|
||||||
|
flags |= UV_HANDLE_WRITABLE;
|
||||||
|
|
||||||
|
return uv__stream_open((uv_stream_t*)handle, fd, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -167,8 +183,7 @@ void uv_pipe_connect(uv_connect_t* req,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(&saddr, 0, sizeof saddr);
|
memset(&saddr, 0, sizeof saddr);
|
||||||
strncpy(saddr.sun_path, name, sizeof(saddr.sun_path) - 1);
|
uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path));
|
||||||
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
|
|
||||||
saddr.sun_family = AF_UNIX;
|
saddr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -194,7 +209,7 @@ void uv_pipe_connect(uv_connect_t* req,
|
|||||||
if (new_sock) {
|
if (new_sock) {
|
||||||
err = uv__stream_open((uv_stream_t*)handle,
|
err = uv__stream_open((uv_stream_t*)handle,
|
||||||
uv__stream_fd(handle),
|
uv__stream_fd(handle),
|
||||||
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
|
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|||||||
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
|
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (uv__fd_exists(loop, fd))
|
||||||
|
return UV_EEXIST;
|
||||||
|
|
||||||
err = uv__io_check_fd(loop, fd);
|
err = uv__io_check_fd(loop, fd);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -250,9 +250,9 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
|
|||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (container->flags & UV_WRITABLE_PIPE)
|
if (container->flags & UV_WRITABLE_PIPE)
|
||||||
flags |= UV_STREAM_READABLE;
|
flags |= UV_HANDLE_READABLE;
|
||||||
if (container->flags & UV_READABLE_PIPE)
|
if (container->flags & UV_READABLE_PIPE)
|
||||||
flags |= UV_STREAM_WRITABLE;
|
flags |= UV_HANDLE_WRITABLE;
|
||||||
|
|
||||||
return uv__stream_open(container->data.stream, pipefds[0], flags);
|
return uv__stream_open(container->data.stream, pipefds[0], flags);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
extern void uv__set_process_title_platform_init(void);
|
||||||
extern void uv__set_process_title(const char* title);
|
extern void uv__set_process_title(const char* title);
|
||||||
|
|
||||||
static uv_mutex_t process_title_mutex;
|
static uv_mutex_t process_title_mutex;
|
||||||
@@ -38,6 +39,9 @@ static struct {
|
|||||||
|
|
||||||
static void init_process_title_mutex_once(void) {
|
static void init_process_title_mutex_once(void) {
|
||||||
uv_mutex_init(&process_title_mutex);
|
uv_mutex_init(&process_title_mutex);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
uv__set_process_title_platform_init();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,8 +54,7 @@ static void uv__signal_unregister_handler(int signum);
|
|||||||
static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
|
static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
|
||||||
static struct uv__signal_tree_s uv__signal_tree =
|
static struct uv__signal_tree_s uv__signal_tree =
|
||||||
RB_INITIALIZER(uv__signal_tree);
|
RB_INITIALIZER(uv__signal_tree);
|
||||||
static int uv__signal_lock_pipefd[2];
|
static int uv__signal_lock_pipefd[2] = { -1, -1 };
|
||||||
|
|
||||||
|
|
||||||
RB_GENERATE_STATIC(uv__signal_tree_s,
|
RB_GENERATE_STATIC(uv__signal_tree_s,
|
||||||
uv_signal_s, tree_entry,
|
uv_signal_s, tree_entry,
|
||||||
@@ -64,7 +63,7 @@ RB_GENERATE_STATIC(uv__signal_tree_s,
|
|||||||
static void uv__signal_global_reinit(void);
|
static void uv__signal_global_reinit(void);
|
||||||
|
|
||||||
static void uv__signal_global_init(void) {
|
static void uv__signal_global_init(void) {
|
||||||
if (!uv__signal_lock_pipefd[0])
|
if (uv__signal_lock_pipefd[0] == -1)
|
||||||
/* pthread_atfork can register before and after handlers, one
|
/* pthread_atfork can register before and after handlers, one
|
||||||
* for each child. This only registers one for the child. That
|
* for each child. This only registers one for the child. That
|
||||||
* state is both persistent and cumulative, so if we keep doing
|
* state is both persistent and cumulative, so if we keep doing
|
||||||
@@ -74,6 +73,33 @@ static void uv__signal_global_init(void) {
|
|||||||
if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
|
if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
|
uv__signal_global_reinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
|
||||||
|
/* We can only use signal-safe functions here.
|
||||||
|
* That includes read/write and close, fortunately.
|
||||||
|
* We do all of this directly here instead of resetting
|
||||||
|
* uv__signal_global_init_guard because
|
||||||
|
* uv__signal_global_once_init is only called from uv_loop_init
|
||||||
|
* and this needs to function in existing loops.
|
||||||
|
*/
|
||||||
|
if (uv__signal_lock_pipefd[0] != -1) {
|
||||||
|
uv__close(uv__signal_lock_pipefd[0]);
|
||||||
|
uv__signal_lock_pipefd[0] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uv__signal_lock_pipefd[1] != -1) {
|
||||||
|
uv__close(uv__signal_lock_pipefd[1]);
|
||||||
|
uv__signal_lock_pipefd[1] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void uv__signal_global_reinit(void) {
|
||||||
|
uv__signal_global_fini();
|
||||||
|
|
||||||
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
|
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
@@ -82,28 +108,11 @@ static void uv__signal_global_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void uv__signal_global_reinit(void) {
|
|
||||||
/* We can only use signal-safe functions here.
|
|
||||||
* That includes read/write and close, fortunately.
|
|
||||||
* We do all of this directly here instead of resetting
|
|
||||||
* uv__signal_global_init_guard because
|
|
||||||
* uv__signal_global_once_init is only called from uv_loop_init
|
|
||||||
* and this needs to function in existing loops.
|
|
||||||
*/
|
|
||||||
uv__close(uv__signal_lock_pipefd[0]);
|
|
||||||
uv__signal_lock_pipefd[0] = -1;
|
|
||||||
uv__close(uv__signal_lock_pipefd[1]);
|
|
||||||
uv__signal_lock_pipefd[1] = -1;
|
|
||||||
uv__signal_global_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uv__signal_global_once_init(void) {
|
void uv__signal_global_once_init(void) {
|
||||||
uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
|
uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int uv__signal_lock(void) {
|
static int uv__signal_lock(void) {
|
||||||
int r;
|
int r;
|
||||||
char data;
|
char data;
|
||||||
@@ -387,7 +396,7 @@ static int uv__signal_start(uv_signal_t* handle,
|
|||||||
*/
|
*/
|
||||||
first_handle = uv__signal_first_handle(signum);
|
first_handle = uv__signal_first_handle(signum);
|
||||||
if (first_handle == NULL ||
|
if (first_handle == NULL ||
|
||||||
(!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) {
|
(!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) {
|
||||||
err = uv__signal_register_handler(signum, oneshot);
|
err = uv__signal_register_handler(signum, oneshot);
|
||||||
if (err) {
|
if (err) {
|
||||||
/* Registering the signal handler failed. Must be an invalid signal. */
|
/* Registering the signal handler failed. Must be an invalid signal. */
|
||||||
@@ -398,7 +407,7 @@ static int uv__signal_start(uv_signal_t* handle,
|
|||||||
|
|
||||||
handle->signum = signum;
|
handle->signum = signum;
|
||||||
if (oneshot)
|
if (oneshot)
|
||||||
handle->flags |= UV__SIGNAL_ONE_SHOT;
|
handle->flags |= UV_SIGNAL_ONE_SHOT;
|
||||||
|
|
||||||
RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
|
RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
|
||||||
|
|
||||||
@@ -455,20 +464,20 @@ static void uv__signal_event(uv_loop_t* loop,
|
|||||||
handle = msg->handle;
|
handle = msg->handle;
|
||||||
|
|
||||||
if (msg->signum == handle->signum) {
|
if (msg->signum == handle->signum) {
|
||||||
assert(!(handle->flags & UV_CLOSING));
|
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||||
handle->signal_cb(handle, handle->signum);
|
handle->signal_cb(handle, handle->signum);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->dispatched_signals++;
|
handle->dispatched_signals++;
|
||||||
|
|
||||||
if (handle->flags & UV__SIGNAL_ONE_SHOT)
|
if (handle->flags & UV_SIGNAL_ONE_SHOT)
|
||||||
uv__signal_stop(handle);
|
uv__signal_stop(handle);
|
||||||
|
|
||||||
/* If uv_close was called while there were caught signals that were not
|
/* If uv_close was called while there were caught signals that were not
|
||||||
* yet dispatched, the uv__finish_close was deferred. Make close pending
|
* yet dispatched, the uv__finish_close was deferred. Make close pending
|
||||||
* now if this has happened.
|
* now if this has happened.
|
||||||
*/
|
*/
|
||||||
if ((handle->flags & UV_CLOSING) &&
|
if ((handle->flags & UV_HANDLE_CLOSING) &&
|
||||||
(handle->caught_signals == handle->dispatched_signals)) {
|
(handle->caught_signals == handle->dispatched_signals)) {
|
||||||
uv__make_close_pending((uv_handle_t*) handle);
|
uv__make_close_pending((uv_handle_t*) handle);
|
||||||
}
|
}
|
||||||
@@ -496,11 +505,11 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
|
|||||||
if (w1->signum < w2->signum) return -1;
|
if (w1->signum < w2->signum) return -1;
|
||||||
if (w1->signum > w2->signum) return 1;
|
if (w1->signum > w2->signum) return 1;
|
||||||
|
|
||||||
/* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first
|
/* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first
|
||||||
* handler returned is a one-shot handler, the rest will be too.
|
* handler returned is a one-shot handler, the rest will be too.
|
||||||
*/
|
*/
|
||||||
f1 = w1->flags & UV__SIGNAL_ONE_SHOT;
|
f1 = w1->flags & UV_SIGNAL_ONE_SHOT;
|
||||||
f2 = w2->flags & UV__SIGNAL_ONE_SHOT;
|
f2 = w2->flags & UV_SIGNAL_ONE_SHOT;
|
||||||
if (f1 < f2) return -1;
|
if (f1 < f2) return -1;
|
||||||
if (f1 > f2) return 1;
|
if (f1 > f2) return 1;
|
||||||
|
|
||||||
@@ -549,8 +558,8 @@ static void uv__signal_stop(uv_signal_t* handle) {
|
|||||||
if (first_handle == NULL) {
|
if (first_handle == NULL) {
|
||||||
uv__signal_unregister_handler(handle->signum);
|
uv__signal_unregister_handler(handle->signum);
|
||||||
} else {
|
} else {
|
||||||
rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT;
|
rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT;
|
||||||
first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT;
|
first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT;
|
||||||
if (first_oneshot && !rem_oneshot) {
|
if (first_oneshot && !rem_oneshot) {
|
||||||
ret = uv__signal_register_handler(handle->signum, 1);
|
ret = uv__signal_register_handler(handle->signum, 1);
|
||||||
assert(ret == 0);
|
assert(ret == 0);
|
||||||
|
|||||||
+124
-138
@@ -58,11 +58,19 @@ struct uv__stream_select_s {
|
|||||||
fd_set* swrite;
|
fd_set* swrite;
|
||||||
size_t swrite_sz;
|
size_t swrite_sz;
|
||||||
};
|
};
|
||||||
# define WRITE_RETRY_ON_ERROR(send_handle) \
|
|
||||||
|
/* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
|
||||||
|
* EPROTOTYPE can be returned while trying to write to a socket that is
|
||||||
|
* shutting down. If we retry the write, we should get the expected EPIPE
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR || errno == EPROTOTYPE)
|
||||||
|
# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
|
||||||
(errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
|
(errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
|
||||||
(errno == EMSGSIZE && send_handle))
|
(errno == EMSGSIZE && send_handle != NULL))
|
||||||
#else
|
#else
|
||||||
# define WRITE_RETRY_ON_ERROR(send_handle) \
|
# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR)
|
||||||
|
# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
|
||||||
(errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
|
(errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
|
||||||
#endif /* defined(__APPLE__) */
|
#endif /* defined(__APPLE__) */
|
||||||
|
|
||||||
@@ -220,7 +228,7 @@ static void uv__stream_osx_select(void* arg) {
|
|||||||
uv_sem_wait(&s->async_sem);
|
uv_sem_wait(&s->async_sem);
|
||||||
|
|
||||||
/* Should be processed at this stage */
|
/* Should be processed at this stage */
|
||||||
assert((s->events == 0) || (stream->flags & UV_CLOSING));
|
assert((s->events == 0) || (stream->flags & UV_HANDLE_CLOSING));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +256,7 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) {
|
|||||||
if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT))
|
if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT))
|
||||||
uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT);
|
uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT);
|
||||||
|
|
||||||
if (stream->flags & UV_CLOSING)
|
if (stream->flags & UV_HANDLE_CLOSING)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* NOTE: It is important to do it here, otherwise `select()` might be called
|
/* NOTE: It is important to do it here, otherwise `select()` might be called
|
||||||
@@ -342,7 +350,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
|
|||||||
if (err)
|
if (err)
|
||||||
goto failed_async_init;
|
goto failed_async_init;
|
||||||
|
|
||||||
s->async.flags |= UV__HANDLE_INTERNAL;
|
s->async.flags |= UV_HANDLE_INTERNAL;
|
||||||
uv__handle_unref(&s->async);
|
uv__handle_unref(&s->async);
|
||||||
|
|
||||||
err = uv_sem_init(&s->close_sem, 0);
|
err = uv_sem_init(&s->close_sem, 0);
|
||||||
@@ -407,12 +415,14 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
|
|||||||
stream->flags |= flags;
|
stream->flags |= flags;
|
||||||
|
|
||||||
if (stream->type == UV_TCP) {
|
if (stream->type == UV_TCP) {
|
||||||
if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
|
if ((stream->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
|
||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
/* TODO Use delay the user passed in. */
|
/* TODO Use delay the user passed in. */
|
||||||
if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60))
|
if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) &&
|
||||||
|
uv__tcp_keepalive(fd, 1, 60)) {
|
||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@@ -447,7 +457,7 @@ void uv__stream_flush_write_queue(uv_stream_t* stream, int error) {
|
|||||||
|
|
||||||
void uv__stream_destroy(uv_stream_t* stream) {
|
void uv__stream_destroy(uv_stream_t* stream) {
|
||||||
assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT));
|
assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT));
|
||||||
assert(stream->flags & UV_CLOSED);
|
assert(stream->flags & UV_HANDLE_CLOSED);
|
||||||
|
|
||||||
if (stream->connect_req) {
|
if (stream->connect_req) {
|
||||||
uv__req_unregister(stream->loop, stream->connect_req);
|
uv__req_unregister(stream->loop, stream->connect_req);
|
||||||
@@ -522,7 +532,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|||||||
stream = container_of(w, uv_stream_t, io_watcher);
|
stream = container_of(w, uv_stream_t, io_watcher);
|
||||||
assert(events & POLLIN);
|
assert(events & POLLIN);
|
||||||
assert(stream->accepted_fd == -1);
|
assert(stream->accepted_fd == -1);
|
||||||
assert(!(stream->flags & UV_CLOSING));
|
assert(!(stream->flags & UV_HANDLE_CLOSING));
|
||||||
|
|
||||||
uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
|
uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
|
||||||
|
|
||||||
@@ -565,7 +575,8 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->type == UV_TCP && (stream->flags & UV_TCP_SINGLE_ACCEPT)) {
|
if (stream->type == UV_TCP &&
|
||||||
|
(stream->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
|
||||||
/* Give other processes a chance to accept connections. */
|
/* Give other processes a chance to accept connections. */
|
||||||
struct timespec timeout = { 0, 1 };
|
struct timespec timeout = { 0, 1 };
|
||||||
nanosleep(&timeout, NULL);
|
nanosleep(&timeout, NULL);
|
||||||
@@ -590,7 +601,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
|
|||||||
case UV_TCP:
|
case UV_TCP:
|
||||||
err = uv__stream_open(client,
|
err = uv__stream_open(client,
|
||||||
server->accepted_fd,
|
server->accepted_fd,
|
||||||
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
|
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||||
if (err) {
|
if (err) {
|
||||||
/* TODO handle error */
|
/* TODO handle error */
|
||||||
uv__close(server->accepted_fd);
|
uv__close(server->accepted_fd);
|
||||||
@@ -674,14 +685,14 @@ static void uv__drain(uv_stream_t* stream) {
|
|||||||
uv__stream_osx_interrupt_select(stream);
|
uv__stream_osx_interrupt_select(stream);
|
||||||
|
|
||||||
/* Shutdown? */
|
/* Shutdown? */
|
||||||
if ((stream->flags & UV_STREAM_SHUTTING) &&
|
if ((stream->flags & UV_HANDLE_SHUTTING) &&
|
||||||
!(stream->flags & UV_CLOSING) &&
|
!(stream->flags & UV_HANDLE_CLOSING) &&
|
||||||
!(stream->flags & UV_STREAM_SHUT)) {
|
!(stream->flags & UV_HANDLE_SHUT)) {
|
||||||
assert(stream->shutdown_req);
|
assert(stream->shutdown_req);
|
||||||
|
|
||||||
req = stream->shutdown_req;
|
req = stream->shutdown_req;
|
||||||
stream->shutdown_req = NULL;
|
stream->shutdown_req = NULL;
|
||||||
stream->flags &= ~UV_STREAM_SHUTTING;
|
stream->flags &= ~UV_HANDLE_SHUTTING;
|
||||||
uv__req_unregister(stream->loop, req);
|
uv__req_unregister(stream->loop, req);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
@@ -689,7 +700,7 @@ static void uv__drain(uv_stream_t* stream) {
|
|||||||
err = UV__ERR(errno);
|
err = UV__ERR(errno);
|
||||||
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
stream->flags |= UV_STREAM_SHUT;
|
stream->flags |= UV_HANDLE_SHUT;
|
||||||
|
|
||||||
if (req->cb != NULL)
|
if (req->cb != NULL)
|
||||||
req->cb(req, err);
|
req->cb(req, err);
|
||||||
@@ -697,6 +708,14 @@ static void uv__drain(uv_stream_t* stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t uv__writev(int fd, struct iovec* vec, size_t n) {
|
||||||
|
if (n == 1)
|
||||||
|
return write(fd, vec->iov_base, vec->iov_len);
|
||||||
|
else
|
||||||
|
return writev(fd, vec, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t uv__write_req_size(uv_write_t* req) {
|
static size_t uv__write_req_size(uv_write_t* req) {
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
@@ -709,6 +728,37 @@ static size_t uv__write_req_size(uv_write_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Returns 1 if all write request data has been written, or 0 if there is still
|
||||||
|
* more data to write.
|
||||||
|
*
|
||||||
|
* Note: the return value only says something about the *current* request.
|
||||||
|
* There may still be other write requests sitting in the queue.
|
||||||
|
*/
|
||||||
|
static int uv__write_req_update(uv_stream_t* stream,
|
||||||
|
uv_write_t* req,
|
||||||
|
size_t n) {
|
||||||
|
uv_buf_t* buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
assert(n <= stream->write_queue_size);
|
||||||
|
stream->write_queue_size -= n;
|
||||||
|
|
||||||
|
buf = req->bufs + req->write_index;
|
||||||
|
|
||||||
|
while (n > 0) {
|
||||||
|
len = n < buf->len ? n : buf->len;
|
||||||
|
buf->base += len;
|
||||||
|
buf->len -= len;
|
||||||
|
buf += (buf->len == 0); /* Advance to next buffer if this one is empty. */
|
||||||
|
n -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->write_index = buf - req->bufs;
|
||||||
|
|
||||||
|
return req->write_index == req->nbufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void uv__write_req_finish(uv_write_t* req) {
|
static void uv__write_req_finish(uv_write_t* req) {
|
||||||
uv_stream_t* stream = req->handle;
|
uv_stream_t* stream = req->handle;
|
||||||
|
|
||||||
@@ -829,102 +879,32 @@ start:
|
|||||||
*pi = fd_to_send;
|
*pi = fd_to_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do
|
||||||
n = sendmsg(uv__stream_fd(stream), &msg, 0);
|
n = sendmsg(uv__stream_fd(stream), &msg, 0);
|
||||||
}
|
while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
|
||||||
#if defined(__APPLE__)
|
|
||||||
/*
|
/* Ensure the handle isn't sent again in case this is a partial write. */
|
||||||
* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
|
if (n >= 0)
|
||||||
* EPROTOTYPE can be returned while trying to write to a socket that is
|
req->send_handle = NULL;
|
||||||
* shutting down. If we retry the write, we should get the expected EPIPE
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
|
|
||||||
#else
|
|
||||||
while (n == -1 && errno == EINTR);
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
do {
|
do
|
||||||
if (iovcnt == 1) {
|
n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
|
||||||
n = write(uv__stream_fd(stream), iov[0].iov_base, iov[0].iov_len);
|
while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
|
||||||
} else {
|
|
||||||
n = writev(uv__stream_fd(stream), iov, iovcnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
/*
|
|
||||||
* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
|
|
||||||
* EPROTOTYPE can be returned while trying to write to a socket that is
|
|
||||||
* shutting down. If we retry the write, we should get the expected EPIPE
|
|
||||||
* instead.
|
|
||||||
*/
|
|
||||||
while (n == -1 && (errno == EINTR || errno == EPROTOTYPE));
|
|
||||||
#else
|
|
||||||
while (n == -1 && errno == EINTR);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n < 0) {
|
if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) {
|
||||||
if (!WRITE_RETRY_ON_ERROR(req->send_handle)) {
|
err = UV__ERR(errno);
|
||||||
err = UV__ERR(errno);
|
goto error;
|
||||||
goto error;
|
|
||||||
} else if (stream->flags & UV_STREAM_BLOCKING) {
|
|
||||||
/* If this is a blocking stream, try again. */
|
|
||||||
goto start;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Successful write */
|
|
||||||
|
|
||||||
while (n >= 0) {
|
|
||||||
uv_buf_t* buf = &(req->bufs[req->write_index]);
|
|
||||||
size_t len = buf->len;
|
|
||||||
|
|
||||||
assert(req->write_index < req->nbufs);
|
|
||||||
|
|
||||||
if ((size_t)n < len) {
|
|
||||||
buf->base += n;
|
|
||||||
buf->len -= n;
|
|
||||||
stream->write_queue_size -= n;
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
/* There is more to write. */
|
|
||||||
if (stream->flags & UV_STREAM_BLOCKING) {
|
|
||||||
/*
|
|
||||||
* If we're blocking then we should not be enabling the write
|
|
||||||
* watcher - instead we need to try again.
|
|
||||||
*/
|
|
||||||
goto start;
|
|
||||||
} else {
|
|
||||||
/* Break loop and ensure the watcher is pending. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Finished writing the buf at index req->write_index. */
|
|
||||||
req->write_index++;
|
|
||||||
|
|
||||||
assert((size_t)n >= len);
|
|
||||||
n -= len;
|
|
||||||
|
|
||||||
assert(stream->write_queue_size >= len);
|
|
||||||
stream->write_queue_size -= len;
|
|
||||||
|
|
||||||
if (req->write_index == req->nbufs) {
|
|
||||||
/* Then we're done! */
|
|
||||||
assert(n == 0);
|
|
||||||
uv__write_req_finish(req);
|
|
||||||
/* TODO: start trying to write the next request. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Either we've counted n down to zero or we've got EAGAIN. */
|
if (n > 0 && uv__write_req_update(stream, req, n)) {
|
||||||
assert(n == 0 || n == -1);
|
uv__write_req_finish(req);
|
||||||
|
return; /* TODO(bnoordhuis) Start trying to write the next request. */
|
||||||
|
}
|
||||||
|
|
||||||
/* Only non-blocking streams should use the write_watcher. */
|
/* If this is a blocking stream, try again. */
|
||||||
assert(!(stream->flags & UV_STREAM_BLOCKING));
|
if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
|
||||||
|
goto start;
|
||||||
|
|
||||||
/* We're not done. */
|
/* We're not done. */
|
||||||
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
||||||
@@ -947,10 +927,16 @@ error:
|
|||||||
static void uv__write_callbacks(uv_stream_t* stream) {
|
static void uv__write_callbacks(uv_stream_t* stream) {
|
||||||
uv_write_t* req;
|
uv_write_t* req;
|
||||||
QUEUE* q;
|
QUEUE* q;
|
||||||
|
QUEUE pq;
|
||||||
|
|
||||||
while (!QUEUE_EMPTY(&stream->write_completed_queue)) {
|
if (QUEUE_EMPTY(&stream->write_completed_queue))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QUEUE_MOVE(&stream->write_completed_queue, &pq);
|
||||||
|
|
||||||
|
while (!QUEUE_EMPTY(&pq)) {
|
||||||
/* Pop a req off write_completed_queue. */
|
/* Pop a req off write_completed_queue. */
|
||||||
q = QUEUE_HEAD(&stream->write_completed_queue);
|
q = QUEUE_HEAD(&pq);
|
||||||
req = QUEUE_DATA(q, uv_write_t, queue);
|
req = QUEUE_DATA(q, uv_write_t, queue);
|
||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
uv__req_unregister(stream->loop, req);
|
uv__req_unregister(stream->loop, req);
|
||||||
@@ -966,8 +952,6 @@ static void uv__write_callbacks(uv_stream_t* stream) {
|
|||||||
if (req->cb)
|
if (req->cb)
|
||||||
req->cb(req, req->error);
|
req->cb(req, req->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(QUEUE_EMPTY(&stream->write_completed_queue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1015,13 +999,13 @@ uv_handle_type uv__handle_type(int fd) {
|
|||||||
|
|
||||||
|
|
||||||
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
|
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
|
||||||
stream->flags |= UV_STREAM_READ_EOF;
|
stream->flags |= UV_HANDLE_READ_EOF;
|
||||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
|
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
|
||||||
if (!uv__io_active(&stream->io_watcher, POLLOUT))
|
if (!uv__io_active(&stream->io_watcher, POLLOUT))
|
||||||
uv__handle_stop(stream);
|
uv__handle_stop(stream);
|
||||||
uv__stream_osx_interrupt_select(stream);
|
uv__stream_osx_interrupt_select(stream);
|
||||||
stream->read_cb(stream, UV_EOF, buf);
|
stream->read_cb(stream, UV_EOF, buf);
|
||||||
stream->flags &= ~UV_STREAM_READING;
|
stream->flags &= ~UV_HANDLE_READING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1121,6 +1105,7 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
|
|||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# pragma clang diagnostic push
|
# pragma clang diagnostic push
|
||||||
# pragma clang diagnostic ignored "-Wgnu-folding-constant"
|
# pragma clang diagnostic ignored "-Wgnu-folding-constant"
|
||||||
|
# pragma clang diagnostic ignored "-Wvla-extension"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void uv__read(uv_stream_t* stream) {
|
static void uv__read(uv_stream_t* stream) {
|
||||||
@@ -1132,7 +1117,7 @@ static void uv__read(uv_stream_t* stream) {
|
|||||||
int err;
|
int err;
|
||||||
int is_ipc;
|
int is_ipc;
|
||||||
|
|
||||||
stream->flags &= ~UV_STREAM_READ_PARTIAL;
|
stream->flags &= ~UV_HANDLE_READ_PARTIAL;
|
||||||
|
|
||||||
/* Prevent loop starvation when the data comes in as fast as (or faster than)
|
/* Prevent loop starvation when the data comes in as fast as (or faster than)
|
||||||
* we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
|
* we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
|
||||||
@@ -1141,11 +1126,11 @@ static void uv__read(uv_stream_t* stream) {
|
|||||||
|
|
||||||
is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc;
|
is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc;
|
||||||
|
|
||||||
/* XXX: Maybe instead of having UV_STREAM_READING we just test if
|
/* XXX: Maybe instead of having UV_HANDLE_READING we just test if
|
||||||
* tcp->read_cb is NULL or not?
|
* tcp->read_cb is NULL or not?
|
||||||
*/
|
*/
|
||||||
while (stream->read_cb
|
while (stream->read_cb
|
||||||
&& (stream->flags & UV_STREAM_READING)
|
&& (stream->flags & UV_HANDLE_READING)
|
||||||
&& (count-- > 0)) {
|
&& (count-- > 0)) {
|
||||||
assert(stream->alloc_cb != NULL);
|
assert(stream->alloc_cb != NULL);
|
||||||
|
|
||||||
@@ -1186,7 +1171,7 @@ static void uv__read(uv_stream_t* stream) {
|
|||||||
/* Error */
|
/* Error */
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
/* Wait for the next one. */
|
/* Wait for the next one. */
|
||||||
if (stream->flags & UV_STREAM_READING) {
|
if (stream->flags & UV_HANDLE_READING) {
|
||||||
uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
|
uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
|
||||||
uv__stream_osx_interrupt_select(stream);
|
uv__stream_osx_interrupt_select(stream);
|
||||||
}
|
}
|
||||||
@@ -1199,8 +1184,8 @@ static void uv__read(uv_stream_t* stream) {
|
|||||||
} else {
|
} else {
|
||||||
/* Error. User should call uv_close(). */
|
/* Error. User should call uv_close(). */
|
||||||
stream->read_cb(stream, UV__ERR(errno), &buf);
|
stream->read_cb(stream, UV__ERR(errno), &buf);
|
||||||
if (stream->flags & UV_STREAM_READING) {
|
if (stream->flags & UV_HANDLE_READING) {
|
||||||
stream->flags &= ~UV_STREAM_READING;
|
stream->flags &= ~UV_HANDLE_READING;
|
||||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
|
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
|
||||||
if (!uv__io_active(&stream->io_watcher, POLLOUT))
|
if (!uv__io_active(&stream->io_watcher, POLLOUT))
|
||||||
uv__handle_stop(stream);
|
uv__handle_stop(stream);
|
||||||
@@ -1250,7 +1235,7 @@ static void uv__read(uv_stream_t* stream) {
|
|||||||
|
|
||||||
/* Return if we didn't fill the buffer, there is no more data to read. */
|
/* Return if we didn't fill the buffer, there is no more data to read. */
|
||||||
if (nread < buflen) {
|
if (nread < buflen) {
|
||||||
stream->flags |= UV_STREAM_READ_PARTIAL;
|
stream->flags |= UV_HANDLE_READ_PARTIAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1271,9 +1256,9 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
|||||||
stream->type == UV_TTY ||
|
stream->type == UV_TTY ||
|
||||||
stream->type == UV_NAMED_PIPE);
|
stream->type == UV_NAMED_PIPE);
|
||||||
|
|
||||||
if (!(stream->flags & UV_STREAM_WRITABLE) ||
|
if (!(stream->flags & UV_HANDLE_WRITABLE) ||
|
||||||
stream->flags & UV_STREAM_SHUT ||
|
stream->flags & UV_HANDLE_SHUT ||
|
||||||
stream->flags & UV_STREAM_SHUTTING ||
|
stream->flags & UV_HANDLE_SHUTTING ||
|
||||||
uv__is_closing(stream)) {
|
uv__is_closing(stream)) {
|
||||||
return UV_ENOTCONN;
|
return UV_ENOTCONN;
|
||||||
}
|
}
|
||||||
@@ -1285,7 +1270,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
|||||||
req->handle = stream;
|
req->handle = stream;
|
||||||
req->cb = cb;
|
req->cb = cb;
|
||||||
stream->shutdown_req = req;
|
stream->shutdown_req = req;
|
||||||
stream->flags |= UV_STREAM_SHUTTING;
|
stream->flags |= UV_HANDLE_SHUTTING;
|
||||||
|
|
||||||
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
||||||
uv__stream_osx_interrupt_select(stream);
|
uv__stream_osx_interrupt_select(stream);
|
||||||
@@ -1302,7 +1287,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|||||||
assert(stream->type == UV_TCP ||
|
assert(stream->type == UV_TCP ||
|
||||||
stream->type == UV_NAMED_PIPE ||
|
stream->type == UV_NAMED_PIPE ||
|
||||||
stream->type == UV_TTY);
|
stream->type == UV_TTY);
|
||||||
assert(!(stream->flags & UV_CLOSING));
|
assert(!(stream->flags & UV_HANDLE_CLOSING));
|
||||||
|
|
||||||
if (stream->connect_req) {
|
if (stream->connect_req) {
|
||||||
uv__stream_connect(stream);
|
uv__stream_connect(stream);
|
||||||
@@ -1311,7 +1296,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|||||||
|
|
||||||
assert(uv__stream_fd(stream) >= 0);
|
assert(uv__stream_fd(stream) >= 0);
|
||||||
|
|
||||||
/* Ignore POLLHUP here. Even it it's set, there may still be data to read. */
|
/* Ignore POLLHUP here. Even if it's set, there may still be data to read. */
|
||||||
if (events & (POLLIN | POLLERR | POLLHUP))
|
if (events & (POLLIN | POLLERR | POLLHUP))
|
||||||
uv__read(stream);
|
uv__read(stream);
|
||||||
|
|
||||||
@@ -1325,9 +1310,9 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
|||||||
* report the EOF yet because there is still data to read.
|
* report the EOF yet because there is still data to read.
|
||||||
*/
|
*/
|
||||||
if ((events & POLLHUP) &&
|
if ((events & POLLHUP) &&
|
||||||
(stream->flags & UV_STREAM_READING) &&
|
(stream->flags & UV_HANDLE_READING) &&
|
||||||
(stream->flags & UV_STREAM_READ_PARTIAL) &&
|
(stream->flags & UV_HANDLE_READ_PARTIAL) &&
|
||||||
!(stream->flags & UV_STREAM_READ_EOF)) {
|
!(stream->flags & UV_HANDLE_READ_EOF)) {
|
||||||
uv_buf_t buf = { NULL, 0 };
|
uv_buf_t buf = { NULL, 0 };
|
||||||
uv__stream_eof(stream, &buf);
|
uv__stream_eof(stream, &buf);
|
||||||
}
|
}
|
||||||
@@ -1417,7 +1402,7 @@ int uv_write2(uv_write_t* req,
|
|||||||
if (uv__stream_fd(stream) < 0)
|
if (uv__stream_fd(stream) < 0)
|
||||||
return UV_EBADF;
|
return UV_EBADF;
|
||||||
|
|
||||||
if (!(stream->flags & UV_STREAM_WRITABLE))
|
if (!(stream->flags & UV_HANDLE_WRITABLE))
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
|
|
||||||
if (send_handle) {
|
if (send_handle) {
|
||||||
@@ -1487,7 +1472,7 @@ int uv_write2(uv_write_t* req,
|
|||||||
* if this assert fires then somehow the blocking stream isn't being
|
* if this assert fires then somehow the blocking stream isn't being
|
||||||
* sufficiently flushed in uv__write.
|
* sufficiently flushed in uv__write.
|
||||||
*/
|
*/
|
||||||
assert(!(stream->flags & UV_STREAM_BLOCKING));
|
assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES));
|
||||||
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
|
||||||
uv__stream_osx_interrupt_select(stream);
|
uv__stream_osx_interrupt_select(stream);
|
||||||
}
|
}
|
||||||
@@ -1568,16 +1553,16 @@ int uv_read_start(uv_stream_t* stream,
|
|||||||
assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
|
assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
|
||||||
stream->type == UV_TTY);
|
stream->type == UV_TTY);
|
||||||
|
|
||||||
if (stream->flags & UV_CLOSING)
|
if (stream->flags & UV_HANDLE_CLOSING)
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
if (!(stream->flags & UV_STREAM_READABLE))
|
if (!(stream->flags & UV_HANDLE_READABLE))
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
|
|
||||||
/* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just
|
/* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
|
||||||
* expresses the desired state of the user.
|
* expresses the desired state of the user.
|
||||||
*/
|
*/
|
||||||
stream->flags |= UV_STREAM_READING;
|
stream->flags |= UV_HANDLE_READING;
|
||||||
|
|
||||||
/* TODO: try to do the read inline? */
|
/* TODO: try to do the read inline? */
|
||||||
/* TODO: keep track of tcp state. If we've gotten a EOF then we should
|
/* TODO: keep track of tcp state. If we've gotten a EOF then we should
|
||||||
@@ -1598,10 +1583,10 @@ int uv_read_start(uv_stream_t* stream,
|
|||||||
|
|
||||||
|
|
||||||
int uv_read_stop(uv_stream_t* stream) {
|
int uv_read_stop(uv_stream_t* stream) {
|
||||||
if (!(stream->flags & UV_STREAM_READING))
|
if (!(stream->flags & UV_HANDLE_READING))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
stream->flags &= ~UV_STREAM_READING;
|
stream->flags &= ~UV_HANDLE_READING;
|
||||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
|
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
|
||||||
if (!uv__io_active(&stream->io_watcher, POLLOUT))
|
if (!uv__io_active(&stream->io_watcher, POLLOUT))
|
||||||
uv__handle_stop(stream);
|
uv__handle_stop(stream);
|
||||||
@@ -1614,12 +1599,12 @@ int uv_read_stop(uv_stream_t* stream) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_is_readable(const uv_stream_t* stream) {
|
int uv_is_readable(const uv_stream_t* stream) {
|
||||||
return !!(stream->flags & UV_STREAM_READABLE);
|
return !!(stream->flags & UV_HANDLE_READABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_is_writable(const uv_stream_t* stream) {
|
int uv_is_writable(const uv_stream_t* stream) {
|
||||||
return !!(stream->flags & UV_STREAM_WRITABLE);
|
return !!(stream->flags & UV_HANDLE_WRITABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1668,6 +1653,7 @@ void uv__stream_close(uv_stream_t* handle) {
|
|||||||
uv__io_close(handle->loop, &handle->io_watcher);
|
uv__io_close(handle->loop, &handle->io_watcher);
|
||||||
uv_read_stop(handle);
|
uv_read_stop(handle);
|
||||||
uv__handle_stop(handle);
|
uv__handle_stop(handle);
|
||||||
|
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||||
|
|
||||||
if (handle->io_watcher.fd != -1) {
|
if (handle->io_watcher.fd != -1) {
|
||||||
/* Don't close stdio file descriptors. Nothing good comes from it. */
|
/* Don't close stdio file descriptors. Nothing good comes from it. */
|
||||||
|
|||||||
@@ -696,6 +696,8 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
|||||||
|
|
||||||
#ifdef SUNOS_NO_IFADDRS
|
#ifdef SUNOS_NO_IFADDRS
|
||||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||||
|
*count = 0;
|
||||||
|
*addresses = NULL;
|
||||||
return UV_ENOSYS;
|
return UV_ENOSYS;
|
||||||
}
|
}
|
||||||
#else /* SUNOS_NO_IFADDRS */
|
#else /* SUNOS_NO_IFADDRS */
|
||||||
@@ -709,13 +711,14 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
|
|||||||
|
|
||||||
struct sockaddr_dl* sa_addr;
|
struct sockaddr_dl* sa_addr;
|
||||||
int sockfd;
|
int sockfd;
|
||||||
int i;
|
size_t i;
|
||||||
struct arpreq arpreq;
|
struct arpreq arpreq;
|
||||||
|
|
||||||
/* This appears to only work as root */
|
/* This appears to only work as root */
|
||||||
sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
|
sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
|
||||||
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
|
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
|
||||||
for (i = 0; i < sizeof(address->phys_addr); i++) {
|
for (i = 0; i < sizeof(address->phys_addr); i++) {
|
||||||
|
/* Check that all bytes of phys_addr are zero. */
|
||||||
if (address->phys_addr[i] != 0)
|
if (address->phys_addr[i] != 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -762,11 +765,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
struct ifaddrs* addrs;
|
struct ifaddrs* addrs;
|
||||||
struct ifaddrs* ent;
|
struct ifaddrs* ent;
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
*addresses = NULL;
|
||||||
|
|
||||||
if (getifaddrs(&addrs))
|
if (getifaddrs(&addrs))
|
||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
/* Count the number of interfaces */
|
/* Count the number of interfaces */
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent))
|
if (uv__ifaddr_exclude(ent))
|
||||||
@@ -774,6 +778,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*count == 0) {
|
||||||
|
freeifaddrs(addrs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*addresses = uv__malloc(*count * sizeof(**addresses));
|
*addresses = uv__malloc(*count * sizeof(**addresses));
|
||||||
if (!(*addresses)) {
|
if (!(*addresses)) {
|
||||||
freeifaddrs(addrs);
|
freeifaddrs(addrs);
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ int uv__tcp_connect(uv_connect_t* req,
|
|||||||
|
|
||||||
err = maybe_new_socket(handle,
|
err = maybe_new_socket(handle,
|
||||||
addr->sa_family,
|
addr->sa_family,
|
||||||
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
|
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -263,13 +263,16 @@ int uv__tcp_connect(uv_connect_t* req,
|
|||||||
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
|
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (uv__fd_exists(handle->loop, sock))
|
||||||
|
return UV_EEXIST;
|
||||||
|
|
||||||
err = uv__nonblock(sock, 1);
|
err = uv__nonblock(sock, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return uv__stream_open((uv_stream_t*)handle,
|
return uv__stream_open((uv_stream_t*)handle,
|
||||||
sock,
|
sock,
|
||||||
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
|
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -331,7 +334,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (single_accept)
|
if (single_accept)
|
||||||
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
|
tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
#if defined(__MVS__)
|
#if defined(__MVS__)
|
||||||
@@ -398,9 +401,9 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
handle->flags |= UV_TCP_NODELAY;
|
handle->flags |= UV_HANDLE_TCP_NODELAY;
|
||||||
else
|
else
|
||||||
handle->flags &= ~UV_TCP_NODELAY;
|
handle->flags &= ~UV_HANDLE_TCP_NODELAY;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -416,9 +419,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
handle->flags |= UV_TCP_KEEPALIVE;
|
handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
|
||||||
else
|
else
|
||||||
handle->flags &= ~UV_TCP_KEEPALIVE;
|
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
|
||||||
|
|
||||||
/* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
|
/* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
|
||||||
* uv_tcp_t with an int that's almost never used...
|
* uv_tcp_t with an int that's almost never used...
|
||||||
@@ -430,9 +433,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
|
|||||||
|
|
||||||
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||||
if (enable)
|
if (enable)
|
||||||
handle->flags &= ~UV_TCP_SINGLE_ACCEPT;
|
handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||||
else
|
else
|
||||||
handle->flags |= UV_TCP_SINGLE_ACCEPT;
|
handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,108 +44,119 @@
|
|||||||
#undef NANOSEC
|
#undef NANOSEC
|
||||||
#define NANOSEC ((uint64_t) 1e9)
|
#define NANOSEC ((uint64_t) 1e9)
|
||||||
|
|
||||||
|
#if defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(UV__PTHREAD_BARRIER_FALLBACK)
|
/* Note: guard clauses should match uv_barrier_t's in include/uv/uv-unix.h. */
|
||||||
/* TODO: support barrier_attr */
|
#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
int pthread_barrier_init(pthread_barrier_t* barrier,
|
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||||
const void* barrier_attr,
|
struct _uv_barrier* b;
|
||||||
unsigned count) {
|
|
||||||
int rc;
|
int rc;
|
||||||
_uv_barrier* b;
|
|
||||||
|
|
||||||
if (barrier == NULL || count == 0)
|
if (barrier == NULL || count == 0)
|
||||||
return EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
if (barrier_attr != NULL)
|
|
||||||
return ENOTSUP;
|
|
||||||
|
|
||||||
b = uv__malloc(sizeof(*b));
|
b = uv__malloc(sizeof(*b));
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
return ENOMEM;
|
return UV_ENOMEM;
|
||||||
|
|
||||||
b->in = 0;
|
b->in = 0;
|
||||||
b->out = 0;
|
b->out = 0;
|
||||||
b->threshold = count;
|
b->threshold = count;
|
||||||
|
|
||||||
if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0)
|
rc = uv_mutex_init(&b->mutex);
|
||||||
|
if (rc != 0)
|
||||||
goto error2;
|
goto error2;
|
||||||
if ((rc = pthread_cond_init(&b->cond, NULL)) != 0)
|
|
||||||
|
rc = uv_cond_init(&b->cond);
|
||||||
|
if (rc != 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
barrier->b = b;
|
barrier->b = b;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
pthread_mutex_destroy(&b->mutex);
|
uv_mutex_destroy(&b->mutex);
|
||||||
error2:
|
error2:
|
||||||
uv__free(b);
|
uv__free(b);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_barrier_wait(pthread_barrier_t* barrier) {
|
|
||||||
int rc;
|
int uv_barrier_wait(uv_barrier_t* barrier) {
|
||||||
_uv_barrier* b;
|
struct _uv_barrier* b;
|
||||||
|
int last;
|
||||||
|
|
||||||
if (barrier == NULL || barrier->b == NULL)
|
if (barrier == NULL || barrier->b == NULL)
|
||||||
return EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
b = barrier->b;
|
b = barrier->b;
|
||||||
/* Lock the mutex*/
|
uv_mutex_lock(&b->mutex);
|
||||||
if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
/* Increment the count. If this is the first thread to reach the threshold,
|
|
||||||
wake up waiters, unlock the mutex, then return
|
|
||||||
PTHREAD_BARRIER_SERIAL_THREAD. */
|
|
||||||
if (++b->in == b->threshold) {
|
if (++b->in == b->threshold) {
|
||||||
b->in = 0;
|
b->in = 0;
|
||||||
b->out = b->threshold - 1;
|
b->out = b->threshold;
|
||||||
rc = pthread_cond_signal(&b->cond);
|
uv_cond_signal(&b->cond);
|
||||||
assert(rc == 0);
|
} else {
|
||||||
|
do
|
||||||
pthread_mutex_unlock(&b->mutex);
|
uv_cond_wait(&b->cond, &b->mutex);
|
||||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
while (b->in != 0);
|
||||||
}
|
}
|
||||||
/* Otherwise, wait for other threads until in is set to 0,
|
|
||||||
then return 0 to indicate this is not the first thread. */
|
|
||||||
do {
|
|
||||||
if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0)
|
|
||||||
break;
|
|
||||||
} while (b->in != 0);
|
|
||||||
|
|
||||||
/* mark thread exit */
|
last = (--b->out == 0);
|
||||||
b->out--;
|
if (!last)
|
||||||
pthread_cond_signal(&b->cond);
|
uv_cond_signal(&b->cond); /* Not needed for last thread. */
|
||||||
pthread_mutex_unlock(&b->mutex);
|
|
||||||
return rc;
|
uv_mutex_unlock(&b->mutex);
|
||||||
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_barrier_destroy(pthread_barrier_t* barrier) {
|
|
||||||
int rc;
|
|
||||||
_uv_barrier* b;
|
|
||||||
|
|
||||||
if (barrier == NULL || barrier->b == NULL)
|
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
||||||
return EINVAL;
|
struct _uv_barrier* b;
|
||||||
|
|
||||||
b = barrier->b;
|
b = barrier->b;
|
||||||
|
uv_mutex_lock(&b->mutex);
|
||||||
|
|
||||||
if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
|
assert(b->in == 0);
|
||||||
return rc;
|
assert(b->out == 0);
|
||||||
|
|
||||||
if (b->in > 0 || b->out > 0)
|
if (b->in != 0 || b->out != 0)
|
||||||
rc = EBUSY;
|
abort();
|
||||||
|
|
||||||
pthread_mutex_unlock(&b->mutex);
|
uv_mutex_unlock(&b->mutex);
|
||||||
|
uv_mutex_destroy(&b->mutex);
|
||||||
|
uv_cond_destroy(&b->cond);
|
||||||
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
pthread_cond_destroy(&b->cond);
|
|
||||||
pthread_mutex_destroy(&b->mutex);
|
|
||||||
uv__free(barrier->b);
|
uv__free(barrier->b);
|
||||||
barrier->b = NULL;
|
barrier->b = NULL;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||||
|
return UV__ERR(pthread_barrier_init(barrier, NULL, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_barrier_wait(uv_barrier_t* barrier) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = pthread_barrier_wait(barrier);
|
||||||
|
if (rc != 0)
|
||||||
|
if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
return rc == PTHREAD_BARRIER_SERIAL_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
||||||
|
if (pthread_barrier_destroy(barrier))
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -771,25 +782,6 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
|
||||||
return UV__ERR(pthread_barrier_init(barrier, NULL, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uv_barrier_destroy(uv_barrier_t* barrier) {
|
|
||||||
if (pthread_barrier_destroy(barrier))
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_barrier_wait(uv_barrier_t* barrier) {
|
|
||||||
int r = pthread_barrier_wait(barrier);
|
|
||||||
if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
|
||||||
abort();
|
|
||||||
return r == PTHREAD_BARRIER_SERIAL_THREAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_key_create(uv_key_t* key) {
|
int uv_key_create(uv_key_t* key) {
|
||||||
return UV__ERR(pthread_key_create(key, NULL));
|
return UV__ERR(pthread_key_create(key, NULL));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,13 +92,15 @@ static int uv__tty_is_slave(const int fd) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) {
|
||||||
uv_handle_type type;
|
uv_handle_type type;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
int newfd = -1;
|
int newfd = -1;
|
||||||
int r;
|
int r;
|
||||||
int saved_flags;
|
int saved_flags;
|
||||||
|
int mode;
|
||||||
char path[256];
|
char path[256];
|
||||||
|
(void)unused; /* deprecated parameter is no longer needed */
|
||||||
|
|
||||||
/* File descriptors that refer to files cannot be monitored with epoll.
|
/* File descriptors that refer to files cannot be monitored with epoll.
|
||||||
* That restriction also applies to character devices like /dev/random
|
* That restriction also applies to character devices like /dev/random
|
||||||
@@ -108,6 +110,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
|||||||
if (type == UV_FILE || type == UV_UNKNOWN_HANDLE)
|
if (type == UV_FILE || type == UV_UNKNOWN_HANDLE)
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
/* Save the fd flags in case we need to restore them due to an error. */
|
||||||
|
do
|
||||||
|
saved_flags = fcntl(fd, F_GETFL);
|
||||||
|
while (saved_flags == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (saved_flags == -1)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
mode = saved_flags & O_ACCMODE;
|
||||||
|
|
||||||
/* Reopen the file descriptor when it refers to a tty. This lets us put the
|
/* Reopen the file descriptor when it refers to a tty. This lets us put the
|
||||||
* tty in non-blocking mode without affecting other processes that share it
|
* tty in non-blocking mode without affecting other processes that share it
|
||||||
* with us.
|
* with us.
|
||||||
@@ -125,14 +136,14 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
|||||||
* slave device.
|
* slave device.
|
||||||
*/
|
*/
|
||||||
if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
|
if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
|
||||||
r = uv__open_cloexec(path, O_RDWR);
|
r = uv__open_cloexec(path, mode);
|
||||||
else
|
else
|
||||||
r = -1;
|
r = -1;
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
/* fallback to using blocking writes */
|
/* fallback to using blocking writes */
|
||||||
if (!readable)
|
if (mode != O_RDONLY)
|
||||||
flags |= UV_STREAM_BLOCKING;
|
flags |= UV_HANDLE_BLOCKING_WRITES;
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,22 +162,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
|
|||||||
fd = newfd;
|
fd = newfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
/* Save the fd flags in case we need to restore them due to an error. */
|
|
||||||
do
|
|
||||||
saved_flags = fcntl(fd, F_GETFL);
|
|
||||||
while (saved_flags == -1 && errno == EINTR);
|
|
||||||
|
|
||||||
if (saved_flags == -1) {
|
|
||||||
if (newfd != -1)
|
|
||||||
uv__close(newfd);
|
|
||||||
return UV__ERR(errno);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Pacify the compiler. */
|
|
||||||
(void) &saved_flags;
|
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
|
uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
|
||||||
|
|
||||||
@@ -174,7 +169,7 @@ skip:
|
|||||||
* the handle queue, since it was added by uv__handle_init in uv_stream_init.
|
* the handle queue, since it was added by uv__handle_init in uv_stream_init.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(flags & UV_STREAM_BLOCKING))
|
if (!(flags & UV_HANDLE_BLOCKING_WRITES))
|
||||||
uv__nonblock(fd, 1);
|
uv__nonblock(fd, 1);
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@@ -191,10 +186,10 @@ skip:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (readable)
|
if (mode != O_WRONLY)
|
||||||
flags |= UV_STREAM_READABLE;
|
flags |= UV_HANDLE_READABLE;
|
||||||
else
|
if (mode != O_RDONLY)
|
||||||
flags |= UV_STREAM_WRITABLE;
|
flags |= UV_HANDLE_WRITABLE;
|
||||||
|
|
||||||
uv__stream_open((uv_stream_t*) tty, fd, flags);
|
uv__stream_open((uv_stream_t*) tty, fd, flags);
|
||||||
tty->mode = UV_TTY_MODE_NORMAL;
|
tty->mode = UV_TTY_MODE_NORMAL;
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
|
|||||||
uv_udp_send_t* req;
|
uv_udp_send_t* req;
|
||||||
QUEUE* q;
|
QUEUE* q;
|
||||||
|
|
||||||
assert(!(handle->flags & UV_UDP_PROCESSING));
|
assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING));
|
||||||
handle->flags |= UV_UDP_PROCESSING;
|
handle->flags |= UV_HANDLE_UDP_PROCESSING;
|
||||||
|
|
||||||
while (!QUEUE_EMPTY(&handle->write_completed_queue)) {
|
while (!QUEUE_EMPTY(&handle->write_completed_queue)) {
|
||||||
q = QUEUE_HEAD(&handle->write_completed_queue);
|
q = QUEUE_HEAD(&handle->write_completed_queue);
|
||||||
@@ -128,7 +128,7 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
|
|||||||
uv__handle_stop(handle);
|
uv__handle_stop(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->flags &= ~UV_UDP_PROCESSING;
|
handle->flags &= ~UV_HANDLE_UDP_PROCESSING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -427,7 +427,7 @@ int uv__udp_send(uv_udp_send_t* req,
|
|||||||
QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
|
QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
|
||||||
uv__handle_start(handle);
|
uv__handle_start(handle);
|
||||||
|
|
||||||
if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) {
|
if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) {
|
||||||
uv__udp_sendmsg(handle);
|
uv__udp_sendmsg(handle);
|
||||||
|
|
||||||
/* `uv__udp_sendmsg` may not be able to do non-blocking write straight
|
/* `uv__udp_sendmsg` may not be able to do non-blocking write straight
|
||||||
@@ -624,6 +624,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
|||||||
if (handle->io_watcher.fd != -1)
|
if (handle->io_watcher.fd != -1)
|
||||||
return UV_EBUSY;
|
return UV_EBUSY;
|
||||||
|
|
||||||
|
if (uv__fd_exists(handle->loop, sock))
|
||||||
|
return UV_EEXIST;
|
||||||
|
|
||||||
err = uv__nonblock(sock, 1);
|
err = uv__nonblock(sock, 1);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@@ -757,14 +760,16 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
|
|||||||
* IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case,
|
* IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case,
|
||||||
* and use the general uv__setsockopt_maybe_char call otherwise.
|
* and use the general uv__setsockopt_maybe_char call otherwise.
|
||||||
*/
|
*/
|
||||||
#if defined(__sun) || defined(_AIX) || defined(__MVS__)
|
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
|
||||||
|
defined(__MVS__)
|
||||||
if (handle->flags & UV_HANDLE_IPV6)
|
if (handle->flags & UV_HANDLE_IPV6)
|
||||||
return uv__setsockopt(handle,
|
return uv__setsockopt(handle,
|
||||||
IP_MULTICAST_TTL,
|
IP_MULTICAST_TTL,
|
||||||
IPV6_MULTICAST_HOPS,
|
IPV6_MULTICAST_HOPS,
|
||||||
&ttl,
|
&ttl,
|
||||||
sizeof(ttl));
|
sizeof(ttl));
|
||||||
#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */
|
#endif /* defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
|
||||||
|
defined(__MVS__) */
|
||||||
|
|
||||||
return uv__setsockopt_maybe_char(handle,
|
return uv__setsockopt_maybe_char(handle,
|
||||||
IP_MULTICAST_TTL,
|
IP_MULTICAST_TTL,
|
||||||
@@ -780,14 +785,16 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
|
|||||||
* IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case,
|
* IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case,
|
||||||
* and use the general uv__setsockopt_maybe_char call otherwise.
|
* and use the general uv__setsockopt_maybe_char call otherwise.
|
||||||
*/
|
*/
|
||||||
#if defined(__sun) || defined(_AIX) || defined(__MVS__)
|
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
|
||||||
|
defined(__MVS__)
|
||||||
if (handle->flags & UV_HANDLE_IPV6)
|
if (handle->flags & UV_HANDLE_IPV6)
|
||||||
return uv__setsockopt(handle,
|
return uv__setsockopt(handle,
|
||||||
IP_MULTICAST_LOOP,
|
IP_MULTICAST_LOOP,
|
||||||
IPV6_MULTICAST_LOOP,
|
IPV6_MULTICAST_LOOP,
|
||||||
&on,
|
&on,
|
||||||
sizeof(on));
|
sizeof(on));
|
||||||
#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */
|
#endif /* defined(__sun) || defined(_AIX) ||defined(__OpenBSD__) ||
|
||||||
|
defined(__MVS__) */
|
||||||
|
|
||||||
return uv__setsockopt_maybe_char(handle,
|
return uv__setsockopt_maybe_char(handle,
|
||||||
IP_MULTICAST_LOOP,
|
IP_MULTICAST_LOOP,
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ char* uv__strndup(const char* s, size_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* uv__malloc(size_t size) {
|
void* uv__malloc(size_t size) {
|
||||||
return uv__allocator.local_malloc(size);
|
if (size > 0)
|
||||||
|
return uv__allocator.local_malloc(size);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uv__free(void* ptr) {
|
void uv__free(void* ptr) {
|
||||||
@@ -91,7 +93,10 @@ void* uv__calloc(size_t count, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* uv__realloc(void* ptr, size_t size) {
|
void* uv__realloc(void* ptr, size_t size) {
|
||||||
return uv__allocator.local_realloc(ptr, size);
|
if (size > 0)
|
||||||
|
return uv__allocator.local_realloc(ptr, size);
|
||||||
|
uv__free(ptr);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uv_replace_allocator(uv_malloc_func malloc_func,
|
int uv_replace_allocator(uv_malloc_func malloc_func,
|
||||||
@@ -155,6 +160,18 @@ static const char* uv__unknown_err_code(int err) {
|
|||||||
return copy != NULL ? copy : "Unknown system error";
|
return copy != NULL ? copy : "Unknown system error";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define UV_ERR_NAME_GEN_R(name, _) \
|
||||||
|
case UV_## name: \
|
||||||
|
uv__strscpy(buf, #name, buflen); break;
|
||||||
|
char* uv_err_name_r(int err, char* buf, size_t buflen) {
|
||||||
|
switch (err) {
|
||||||
|
UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
|
||||||
|
default: snprintf(buf, buflen, "Unknown system error %d", err);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
#undef UV_ERR_NAME_GEN_R
|
||||||
|
|
||||||
|
|
||||||
#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
|
#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
|
||||||
const char* uv_err_name(int err) {
|
const char* uv_err_name(int err) {
|
||||||
@@ -166,6 +183,19 @@ const char* uv_err_name(int err) {
|
|||||||
#undef UV_ERR_NAME_GEN
|
#undef UV_ERR_NAME_GEN
|
||||||
|
|
||||||
|
|
||||||
|
#define UV_STRERROR_GEN_R(name, msg) \
|
||||||
|
case UV_ ## name: \
|
||||||
|
snprintf(buf, buflen, "%s", msg); break;
|
||||||
|
char* uv_strerror_r(int err, char* buf, size_t buflen) {
|
||||||
|
switch (err) {
|
||||||
|
UV_ERRNO_MAP(UV_STRERROR_GEN_R)
|
||||||
|
default: snprintf(buf, buflen, "Unknown system error %d", err);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
#undef UV_STRERROR_GEN_R
|
||||||
|
|
||||||
|
|
||||||
#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
|
#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
|
||||||
const char* uv_strerror(int err) {
|
const char* uv_strerror(int err) {
|
||||||
switch (err) {
|
switch (err) {
|
||||||
@@ -359,7 +389,7 @@ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
|
|||||||
QUEUE_REMOVE(q);
|
QUEUE_REMOVE(q);
|
||||||
QUEUE_INSERT_TAIL(&loop->handle_queue, q);
|
QUEUE_INSERT_TAIL(&loop->handle_queue, q);
|
||||||
|
|
||||||
if (h->flags & UV__HANDLE_INTERNAL) continue;
|
if (h->flags & UV_HANDLE_INTERNAL) continue;
|
||||||
walk_cb(h, arg);
|
walk_cb(h, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,9 +418,9 @@ static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
|
|||||||
|
|
||||||
fprintf(stream,
|
fprintf(stream,
|
||||||
"[%c%c%c] %-8s %p\n",
|
"[%c%c%c] %-8s %p\n",
|
||||||
"R-"[!(h->flags & UV__HANDLE_REF)],
|
"R-"[!(h->flags & UV_HANDLE_REF)],
|
||||||
"A-"[!(h->flags & UV__HANDLE_ACTIVE)],
|
"A-"[!(h->flags & UV_HANDLE_ACTIVE)],
|
||||||
"I-"[!(h->flags & UV__HANDLE_INTERNAL)],
|
"I-"[!(h->flags & UV_HANDLE_INTERNAL)],
|
||||||
type,
|
type,
|
||||||
(void*)h);
|
(void*)h);
|
||||||
}
|
}
|
||||||
@@ -634,7 +664,7 @@ int uv_loop_close(uv_loop_t* loop) {
|
|||||||
|
|
||||||
QUEUE_FOREACH(q, &loop->handle_queue) {
|
QUEUE_FOREACH(q, &loop->handle_queue) {
|
||||||
h = QUEUE_DATA(q, uv_handle_t, handle_queue);
|
h = QUEUE_DATA(q, uv_handle_t, handle_queue);
|
||||||
if (!(h->flags & UV__HANDLE_INTERNAL))
|
if (!(h->flags & UV_HANDLE_INTERNAL))
|
||||||
return UV_EBUSY;
|
return UV_EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,14 +32,15 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||||
# include "stdint-msvc2008.h"
|
# include "uv/stdint-msvc2008.h"
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "tree.h"
|
#include "uv/tree.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
#include "strscpy.h"
|
||||||
|
|
||||||
#if EDOM > 0
|
#if EDOM > 0
|
||||||
# define UV__ERR(x) (-(x))
|
# define UV__ERR(x) (-(x))
|
||||||
@@ -59,22 +60,67 @@ extern int snprintf(char*, size_t, const char*, ...);
|
|||||||
#define STATIC_ASSERT(expr) \
|
#define STATIC_ASSERT(expr) \
|
||||||
void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
|
void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
|
||||||
|
|
||||||
#ifndef _WIN32
|
/* Handle flags. Some flags are specific to Windows or UNIX. */
|
||||||
enum {
|
enum {
|
||||||
UV__SIGNAL_ONE_SHOT = 0x80000, /* On signal reception remove sighandler */
|
/* Used by all handles. */
|
||||||
UV__HANDLE_INTERNAL = 0x8000,
|
UV_HANDLE_CLOSING = 0x00000001,
|
||||||
UV__HANDLE_ACTIVE = 0x4000,
|
UV_HANDLE_CLOSED = 0x00000002,
|
||||||
UV__HANDLE_REF = 0x2000,
|
UV_HANDLE_ACTIVE = 0x00000004,
|
||||||
UV__HANDLE_CLOSING = 0 /* no-op on unix */
|
UV_HANDLE_REF = 0x00000008,
|
||||||
|
UV_HANDLE_INTERNAL = 0x00000010,
|
||||||
|
UV_HANDLE_ENDGAME_QUEUED = 0x00000020,
|
||||||
|
|
||||||
|
/* Used by streams. */
|
||||||
|
UV_HANDLE_LISTENING = 0x00000040,
|
||||||
|
UV_HANDLE_CONNECTION = 0x00000080,
|
||||||
|
UV_HANDLE_SHUTTING = 0x00000100,
|
||||||
|
UV_HANDLE_SHUT = 0x00000200,
|
||||||
|
UV_HANDLE_READ_PARTIAL = 0x00000400,
|
||||||
|
UV_HANDLE_READ_EOF = 0x00000800,
|
||||||
|
|
||||||
|
/* Used by streams and UDP handles. */
|
||||||
|
UV_HANDLE_READING = 0x00001000,
|
||||||
|
UV_HANDLE_BOUND = 0x00002000,
|
||||||
|
UV_HANDLE_READABLE = 0x00004000,
|
||||||
|
UV_HANDLE_WRITABLE = 0x00008000,
|
||||||
|
UV_HANDLE_READ_PENDING = 0x00010000,
|
||||||
|
UV_HANDLE_SYNC_BYPASS_IOCP = 0x00020000,
|
||||||
|
UV_HANDLE_ZERO_READ = 0x00040000,
|
||||||
|
UV_HANDLE_EMULATE_IOCP = 0x00080000,
|
||||||
|
UV_HANDLE_BLOCKING_WRITES = 0x00100000,
|
||||||
|
UV_HANDLE_CANCELLATION_PENDING = 0x00200000,
|
||||||
|
|
||||||
|
/* Used by uv_tcp_t and uv_udp_t handles */
|
||||||
|
UV_HANDLE_IPV6 = 0x00400000,
|
||||||
|
|
||||||
|
/* Only used by uv_tcp_t handles. */
|
||||||
|
UV_HANDLE_TCP_NODELAY = 0x01000000,
|
||||||
|
UV_HANDLE_TCP_KEEPALIVE = 0x02000000,
|
||||||
|
UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000,
|
||||||
|
UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000,
|
||||||
|
UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000,
|
||||||
|
UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000,
|
||||||
|
|
||||||
|
/* Only used by uv_udp_t handles. */
|
||||||
|
UV_HANDLE_UDP_PROCESSING = 0x01000000,
|
||||||
|
|
||||||
|
/* Only used by uv_pipe_t handles. */
|
||||||
|
UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000,
|
||||||
|
UV_HANDLE_PIPESERVER = 0x02000000,
|
||||||
|
|
||||||
|
/* Only used by uv_tty_t handles. */
|
||||||
|
UV_HANDLE_TTY_READABLE = 0x01000000,
|
||||||
|
UV_HANDLE_TTY_RAW = 0x02000000,
|
||||||
|
UV_HANDLE_TTY_SAVED_POSITION = 0x04000000,
|
||||||
|
UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000,
|
||||||
|
|
||||||
|
/* Only used by uv_signal_t handles. */
|
||||||
|
UV_SIGNAL_ONE_SHOT_DISPATCHED = 0x01000000,
|
||||||
|
UV_SIGNAL_ONE_SHOT = 0x02000000,
|
||||||
|
|
||||||
|
/* Only used by uv_poll_t handles. */
|
||||||
|
UV_HANDLE_POLL_SLOW = 0x01000000
|
||||||
};
|
};
|
||||||
#else
|
|
||||||
# define UV__SIGNAL_ONE_SHOT_DISPATCHED 0x200
|
|
||||||
# define UV__SIGNAL_ONE_SHOT 0x100
|
|
||||||
# define UV__HANDLE_INTERNAL 0x80
|
|
||||||
# define UV__HANDLE_ACTIVE 0x40
|
|
||||||
# define UV__HANDLE_REF 0x20
|
|
||||||
# define UV__HANDLE_CLOSING 0x01
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
|
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
|
||||||
|
|
||||||
@@ -119,8 +165,15 @@ void uv__fs_poll_close(uv_fs_poll_t* handle);
|
|||||||
|
|
||||||
int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */
|
int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */
|
||||||
|
|
||||||
|
enum uv__work_kind {
|
||||||
|
UV__WORK_CPU,
|
||||||
|
UV__WORK_FAST_IO,
|
||||||
|
UV__WORK_SLOW_IO
|
||||||
|
};
|
||||||
|
|
||||||
void uv__work_submit(uv_loop_t* loop,
|
void uv__work_submit(uv_loop_t* loop,
|
||||||
struct uv__work *w,
|
struct uv__work *w,
|
||||||
|
enum uv__work_kind kind,
|
||||||
void (*work)(struct uv__work *w),
|
void (*work)(struct uv__work *w),
|
||||||
void (*done)(struct uv__work *w, int status));
|
void (*done)(struct uv__work *w, int status));
|
||||||
|
|
||||||
@@ -132,6 +185,10 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
|
|||||||
|
|
||||||
void uv__fs_scandir_cleanup(uv_fs_t* req);
|
void uv__fs_scandir_cleanup(uv_fs_t* req);
|
||||||
|
|
||||||
|
int uv__next_timeout(const uv_loop_t* loop);
|
||||||
|
void uv__run_timers(uv_loop_t* loop);
|
||||||
|
void uv__timer_close(uv_timer_t* handle);
|
||||||
|
|
||||||
#define uv__has_active_reqs(loop) \
|
#define uv__has_active_reqs(loop) \
|
||||||
((loop)->active_reqs.count > 0)
|
((loop)->active_reqs.count > 0)
|
||||||
|
|
||||||
@@ -164,49 +221,47 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
|
|||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#define uv__is_active(h) \
|
#define uv__is_active(h) \
|
||||||
(((h)->flags & UV__HANDLE_ACTIVE) != 0)
|
(((h)->flags & UV_HANDLE_ACTIVE) != 0)
|
||||||
|
|
||||||
#define uv__is_closing(h) \
|
#define uv__is_closing(h) \
|
||||||
(((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0)
|
(((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0)
|
||||||
|
|
||||||
#define uv__handle_start(h) \
|
#define uv__handle_start(h) \
|
||||||
do { \
|
do { \
|
||||||
assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \
|
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \
|
||||||
if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break; \
|
(h)->flags |= UV_HANDLE_ACTIVE; \
|
||||||
(h)->flags |= UV__HANDLE_ACTIVE; \
|
if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \
|
||||||
if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h); \
|
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#define uv__handle_stop(h) \
|
#define uv__handle_stop(h) \
|
||||||
do { \
|
do { \
|
||||||
assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \
|
if (((h)->flags & UV_HANDLE_ACTIVE) == 0) break; \
|
||||||
if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break; \
|
(h)->flags &= ~UV_HANDLE_ACTIVE; \
|
||||||
(h)->flags &= ~UV__HANDLE_ACTIVE; \
|
if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_rm(h); \
|
||||||
if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h); \
|
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#define uv__handle_ref(h) \
|
#define uv__handle_ref(h) \
|
||||||
do { \
|
do { \
|
||||||
if (((h)->flags & UV__HANDLE_REF) != 0) break; \
|
if (((h)->flags & UV_HANDLE_REF) != 0) break; \
|
||||||
(h)->flags |= UV__HANDLE_REF; \
|
(h)->flags |= UV_HANDLE_REF; \
|
||||||
if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \
|
if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \
|
||||||
if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \
|
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#define uv__handle_unref(h) \
|
#define uv__handle_unref(h) \
|
||||||
do { \
|
do { \
|
||||||
if (((h)->flags & UV__HANDLE_REF) == 0) break; \
|
if (((h)->flags & UV_HANDLE_REF) == 0) break; \
|
||||||
(h)->flags &= ~UV__HANDLE_REF; \
|
(h)->flags &= ~UV_HANDLE_REF; \
|
||||||
if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \
|
if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \
|
||||||
if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \
|
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
#define uv__has_ref(h) \
|
#define uv__has_ref(h) \
|
||||||
(((h)->flags & UV__HANDLE_REF) != 0)
|
(((h)->flags & UV_HANDLE_REF) != 0)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
# define uv__handle_platform_init(h) ((h)->u.fd = -1)
|
# define uv__handle_platform_init(h) ((h)->u.fd = -1)
|
||||||
@@ -218,7 +273,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
|
|||||||
do { \
|
do { \
|
||||||
(h)->loop = (loop_); \
|
(h)->loop = (loop_); \
|
||||||
(h)->type = (type_); \
|
(h)->type = (type_); \
|
||||||
(h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \
|
(h)->flags = UV_HANDLE_REF; /* Ref the loop when active. */ \
|
||||||
QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \
|
QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \
|
||||||
uv__handle_platform_init(h); \
|
uv__handle_platform_init(h); \
|
||||||
} \
|
} \
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
const char* uv_handle_type_name(uv_handle_type type) {
|
const char* uv_handle_type_name(uv_handle_type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#define XX(uc,lc) case UV_##uc: return #lc;
|
#define XX(uc,lc) case UV_##uc: return #lc;
|
||||||
UV_HANDLE_TYPE_MAP(XX)
|
UV_HANDLE_TYPE_MAP(XX)
|
||||||
#undef XX
|
#undef XX
|
||||||
case UV_FILE: return "file";
|
case UV_FILE: return "file";
|
||||||
case UV_HANDLE_TYPE_MAX:
|
case UV_HANDLE_TYPE_MAX:
|
||||||
case UV_UNKNOWN_HANDLE: return NULL;
|
case UV_UNKNOWN_HANDLE: return NULL;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -31,10 +31,12 @@ void uv_handle_set_data(uv_handle_t* handle, void* data) {
|
|||||||
const char* uv_req_type_name(uv_req_type type) {
|
const char* uv_req_type_name(uv_req_type type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#define XX(uc,lc) case UV_##uc: return #lc;
|
#define XX(uc,lc) case UV_##uc: return #lc;
|
||||||
UV_REQ_TYPE_MAP(XX)
|
UV_REQ_TYPE_MAP(XX)
|
||||||
#undef XX
|
#undef XX
|
||||||
case UV_REQ_TYPE_MAX:
|
case UV_REQ_TYPE_MAX:
|
||||||
case UV_UNKNOWN_REQ: return NULL;
|
case UV_UNKNOWN_REQ:
|
||||||
|
default: /* UV_REQ_TYPE_PRIVATE */
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
|
void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
|
||||||
if (handle->flags & UV__HANDLE_CLOSING &&
|
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||||
!handle->async_sent) {
|
!handle->async_sent) {
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
uv__handle_close(handle);
|
uv__handle_close(handle);
|
||||||
@@ -71,9 +71,9 @@ int uv_async_send(uv_async_t* handle) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The user should make sure never to call uv_async_send to a closing */
|
/* The user should make sure never to call uv_async_send to a closing or
|
||||||
/* or closed handle. */
|
* closed handle. */
|
||||||
assert(!(handle->flags & UV__HANDLE_CLOSING));
|
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||||
|
|
||||||
if (!uv__atomic_exchange_set(&handle->async_sent)) {
|
if (!uv__atomic_exchange_set(&handle->async_sent)) {
|
||||||
POST_COMPLETION_FOR_REQ(loop, &handle->async_req);
|
POST_COMPLETION_FOR_REQ(loop, &handle->async_req);
|
||||||
@@ -90,7 +90,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
|
|||||||
|
|
||||||
handle->async_sent = 0;
|
handle->async_sent = 0;
|
||||||
|
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
uv_want_endgame(loop, (uv_handle_t*)handle);
|
uv_want_endgame(loop, (uv_handle_t*)handle);
|
||||||
} else if (handle->async_cb != NULL) {
|
} else if (handle->async_cb != NULL) {
|
||||||
handle->async_cb(handle);
|
handle->async_cb(handle);
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
/* Atomic set operation on char */
|
/* Atomic set operation on char */
|
||||||
#ifdef _MSC_VER /* MSVC */
|
#ifdef _MSC_VER /* MSVC */
|
||||||
|
|
||||||
/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */
|
/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less
|
||||||
/* efficient than InterlockedExchange, but InterlockedExchange8 does not */
|
* efficient than InterlockedExchange, but InterlockedExchange8 does not exist,
|
||||||
/* exist, and interlocked operations on larger targets might require the */
|
* and interlocked operations on larger targets might require the target to be
|
||||||
/* target to be aligned. */
|
* aligned. */
|
||||||
#pragma intrinsic(_InterlockedOr8)
|
#pragma intrinsic(_InterlockedOr8)
|
||||||
|
|
||||||
static char INLINE uv__atomic_exchange_set(char volatile* target) {
|
static char INLINE uv__atomic_exchange_set(char volatile* target) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "handle-inl.h"
|
#include "handle-inl.h"
|
||||||
|
#include "heap-inl.h"
|
||||||
#include "req-inl.h"
|
#include "req-inl.h"
|
||||||
|
|
||||||
/* uv_once initialization guards */
|
/* uv_once initialization guards */
|
||||||
@@ -221,6 +222,7 @@ static void uv_init(void) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_loop_init(uv_loop_t* loop) {
|
int uv_loop_init(uv_loop_t* loop) {
|
||||||
|
struct heap* timer_heap;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* Initialize libuv itself first */
|
/* Initialize libuv itself first */
|
||||||
@@ -246,7 +248,13 @@ int uv_loop_init(uv_loop_t* loop) {
|
|||||||
|
|
||||||
loop->endgame_handles = NULL;
|
loop->endgame_handles = NULL;
|
||||||
|
|
||||||
RB_INIT(&loop->timers);
|
loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap));
|
||||||
|
if (timer_heap == NULL) {
|
||||||
|
err = UV_ENOMEM;
|
||||||
|
goto fail_timers_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_init(timer_heap);
|
||||||
|
|
||||||
loop->check_handles = NULL;
|
loop->check_handles = NULL;
|
||||||
loop->prepare_handles = NULL;
|
loop->prepare_handles = NULL;
|
||||||
@@ -273,7 +281,7 @@ int uv_loop_init(uv_loop_t* loop) {
|
|||||||
goto fail_async_init;
|
goto fail_async_init;
|
||||||
|
|
||||||
uv__handle_unref(&loop->wq_async);
|
uv__handle_unref(&loop->wq_async);
|
||||||
loop->wq_async.flags |= UV__HANDLE_INTERNAL;
|
loop->wq_async.flags |= UV_HANDLE_INTERNAL;
|
||||||
|
|
||||||
err = uv__loops_add(loop);
|
err = uv__loops_add(loop);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -285,6 +293,10 @@ fail_async_init:
|
|||||||
uv_mutex_destroy(&loop->wq_mutex);
|
uv_mutex_destroy(&loop->wq_mutex);
|
||||||
|
|
||||||
fail_mutex_init:
|
fail_mutex_init:
|
||||||
|
uv__free(timer_heap);
|
||||||
|
loop->timer_heap = NULL;
|
||||||
|
|
||||||
|
fail_timers_alloc:
|
||||||
CloseHandle(loop->iocp);
|
CloseHandle(loop->iocp);
|
||||||
loop->iocp = INVALID_HANDLE_VALUE;
|
loop->iocp = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
@@ -292,6 +304,13 @@ fail_mutex_init:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void uv_update_time(uv_loop_t* loop) {
|
||||||
|
uint64_t new_time = uv__hrtime(1000);
|
||||||
|
assert(new_time >= loop->time);
|
||||||
|
loop->time = new_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv__once_init(void) {
|
void uv__once_init(void) {
|
||||||
uv_once(&uv_init_guard_, uv_init);
|
uv_once(&uv_init_guard_, uv_init);
|
||||||
}
|
}
|
||||||
@@ -320,6 +339,9 @@ void uv__loop_close(uv_loop_t* loop) {
|
|||||||
uv_mutex_unlock(&loop->wq_mutex);
|
uv_mutex_unlock(&loop->wq_mutex);
|
||||||
uv_mutex_destroy(&loop->wq_mutex);
|
uv_mutex_destroy(&loop->wq_mutex);
|
||||||
|
|
||||||
|
uv__free(loop->timer_heap);
|
||||||
|
loop->timer_heap = NULL;
|
||||||
|
|
||||||
CloseHandle(loop->iocp);
|
CloseHandle(loop->iocp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +381,7 @@ int uv_backend_timeout(const uv_loop_t* loop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void uv_poll(uv_loop_t* loop, DWORD timeout) {
|
static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
ULONG_PTR key;
|
ULONG_PTR key;
|
||||||
OVERLAPPED* overlapped;
|
OVERLAPPED* overlapped;
|
||||||
@@ -410,7 +432,7 @@ static void uv_poll(uv_loop_t* loop, DWORD timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
|
static void uv__poll(uv_loop_t* loop, DWORD timeout) {
|
||||||
BOOL success;
|
BOOL success;
|
||||||
uv_req_t* req;
|
uv_req_t* req;
|
||||||
OVERLAPPED_ENTRY overlappeds[128];
|
OVERLAPPED_ENTRY overlappeds[128];
|
||||||
@@ -422,12 +444,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
|
|||||||
timeout_time = loop->time + timeout;
|
timeout_time = loop->time + timeout;
|
||||||
|
|
||||||
for (repeat = 0; ; repeat++) {
|
for (repeat = 0; ; repeat++) {
|
||||||
success = pGetQueuedCompletionStatusEx(loop->iocp,
|
success = GetQueuedCompletionStatusEx(loop->iocp,
|
||||||
overlappeds,
|
overlappeds,
|
||||||
ARRAY_SIZE(overlappeds),
|
ARRAY_SIZE(overlappeds),
|
||||||
&count,
|
&count,
|
||||||
timeout,
|
timeout,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
@@ -485,12 +507,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
|||||||
DWORD timeout;
|
DWORD timeout;
|
||||||
int r;
|
int r;
|
||||||
int ran_pending;
|
int ran_pending;
|
||||||
void (*poll)(uv_loop_t* loop, DWORD timeout);
|
|
||||||
|
|
||||||
if (pGetQueuedCompletionStatusEx)
|
|
||||||
poll = &uv_poll_ex;
|
|
||||||
else
|
|
||||||
poll = &uv_poll;
|
|
||||||
|
|
||||||
r = uv__loop_alive(loop);
|
r = uv__loop_alive(loop);
|
||||||
if (!r)
|
if (!r)
|
||||||
@@ -498,7 +514,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
|||||||
|
|
||||||
while (r != 0 && loop->stop_flag == 0) {
|
while (r != 0 && loop->stop_flag == 0) {
|
||||||
uv_update_time(loop);
|
uv_update_time(loop);
|
||||||
uv_process_timers(loop);
|
uv__run_timers(loop);
|
||||||
|
|
||||||
ran_pending = uv_process_reqs(loop);
|
ran_pending = uv_process_reqs(loop);
|
||||||
uv_idle_invoke(loop);
|
uv_idle_invoke(loop);
|
||||||
@@ -508,7 +524,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
|||||||
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
|
||||||
timeout = uv_backend_timeout(loop);
|
timeout = uv_backend_timeout(loop);
|
||||||
|
|
||||||
(*poll)(loop, timeout);
|
if (pGetQueuedCompletionStatusEx)
|
||||||
|
uv__poll(loop, timeout);
|
||||||
|
else
|
||||||
|
uv__poll_wine(loop, timeout);
|
||||||
|
|
||||||
|
|
||||||
uv_check_invoke(loop);
|
uv_check_invoke(loop);
|
||||||
uv_process_endgames(loop);
|
uv_process_endgames(loop);
|
||||||
@@ -522,7 +542,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
|
|||||||
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
|
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
|
||||||
* the check.
|
* the check.
|
||||||
*/
|
*/
|
||||||
uv_process_timers(loop);
|
uv__run_timers(loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = uv__loop_alive(loop);
|
r = uv__loop_alive(loop);
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ void uv_dlclose(uv_lib_t* lib) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
|
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
|
||||||
*ptr = (void*) GetProcAddress(lib->handle, name);
|
/* Cast though integer to suppress pedantic warning about forbidden cast. */
|
||||||
|
*ptr = (void*)(uintptr_t) GetProcAddress(lib->handle, name);
|
||||||
return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());
|
return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +76,9 @@ const char* uv_dlerror(const uv_lib_t* lib) {
|
|||||||
|
|
||||||
|
|
||||||
static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
|
static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
|
||||||
DWORD_PTR args[1] = { (DWORD_PTR) errorno };
|
static const CHAR fallback_error[] = "error: %1!d!";
|
||||||
LPSTR fallback_error = "error: %1!d!";
|
DWORD_PTR args[1];
|
||||||
|
args[0] = (DWORD_PTR) errorno;
|
||||||
|
|
||||||
FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
|
FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
|
||||||
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
||||||
@@ -107,7 +109,8 @@ static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) {
|
|||||||
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
||||||
(LPSTR) &lib->errmsg, 0, NULL);
|
(LPSTR) &lib->errmsg, 0, NULL);
|
||||||
|
|
||||||
if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
|
if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND ||
|
||||||
|
GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) {
|
||||||
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
|
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ void uv_fatal_error(const int errorno, const char* syscall) {
|
|||||||
errmsg = "Unknown error";
|
errmsg = "Unknown error";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FormatMessage messages include a newline character already, */
|
/* FormatMessage messages include a newline character already, so don't add
|
||||||
/* so don't add another. */
|
* another. */
|
||||||
if (syscall) {
|
if (syscall) {
|
||||||
fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);
|
fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static void uv_relative_path(const WCHAR* filename,
|
|||||||
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
|
static int uv_split_path(const WCHAR* filename, WCHAR** dir,
|
||||||
WCHAR** file) {
|
WCHAR** file) {
|
||||||
size_t len, i;
|
size_t len, i;
|
||||||
|
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
if (dir != NULL)
|
if (dir != NULL)
|
||||||
*dir = NULL;
|
*dir = NULL;
|
||||||
@@ -215,11 +215,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
uv__free(long_path);
|
uv__free(long_path);
|
||||||
long_path = NULL;
|
long_path = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (long_path) {
|
if (long_path) {
|
||||||
uv__free(pathw);
|
uv__free(pathw);
|
||||||
pathw = long_path;
|
pathw = long_path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_to_watch = pathw;
|
dir_to_watch = pathw;
|
||||||
@@ -230,8 +230,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Convert to short path. */
|
/* Convert to short path. */
|
||||||
short_path = short_path_buffer;
|
if (GetShortPathNameW(pathw,
|
||||||
if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) {
|
short_path_buffer,
|
||||||
|
ARRAY_SIZE(short_path_buffer))) {
|
||||||
|
short_path = short_path_buffer;
|
||||||
|
} else {
|
||||||
short_path = NULL;
|
short_path = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +422,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
|||||||
* - We are not active, just ignore the callback
|
* - We are not active, just ignore the callback
|
||||||
*/
|
*/
|
||||||
if (!uv__is_active(handle)) {
|
if (!uv__is_active(handle)) {
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -543,7 +546,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset = file_info->NextEntryOffset;
|
offset = file_info->NextEntryOffset;
|
||||||
} while (offset && !(handle->flags & UV__HANDLE_CLOSING));
|
} while (offset && !(handle->flags & UV_HANDLE_CLOSING));
|
||||||
} else {
|
} else {
|
||||||
handle->cb(handle, NULL, UV_CHANGE, 0);
|
handle->cb(handle, NULL, UV_CHANGE, 0);
|
||||||
}
|
}
|
||||||
@@ -552,7 +555,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
|||||||
handle->cb(handle, NULL, 0, uv_translate_sys_error(err));
|
handle->cb(handle, NULL, 0, uv_translate_sys_error(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(handle->flags & UV__HANDLE_CLOSING)) {
|
if (!(handle->flags & UV_HANDLE_CLOSING)) {
|
||||||
uv_fs_event_queue_readdirchanges(loop, handle);
|
uv_fs_event_queue_readdirchanges(loop, handle);
|
||||||
} else {
|
} else {
|
||||||
uv_want_endgame(loop, (uv_handle_t*)handle);
|
uv_want_endgame(loop, (uv_handle_t*)handle);
|
||||||
@@ -573,7 +576,7 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
|
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||||
if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) {
|
if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) {
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
|
|
||||||
if (handle->buffer) {
|
if (handle->buffer) {
|
||||||
|
|||||||
+133
-51
@@ -55,7 +55,11 @@
|
|||||||
do { \
|
do { \
|
||||||
if (cb != NULL) { \
|
if (cb != NULL) { \
|
||||||
uv__req_register(loop, req); \
|
uv__req_register(loop, req); \
|
||||||
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
|
uv__work_submit(loop, \
|
||||||
|
&req->work_req, \
|
||||||
|
UV__WORK_FAST_IO, \
|
||||||
|
uv__fs_work, \
|
||||||
|
uv__fs_done); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} else { \
|
} else { \
|
||||||
uv__fs_work(&req->work_req); \
|
uv__fs_work(&req->work_req); \
|
||||||
@@ -92,14 +96,17 @@
|
|||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MILLIONu (1000U * 1000U)
|
||||||
|
#define BILLIONu (1000U * 1000U * 1000U)
|
||||||
|
|
||||||
#define FILETIME_TO_UINT(filetime) \
|
#define FILETIME_TO_UINT(filetime) \
|
||||||
(*((uint64_t*) &(filetime)) - 116444736000000000ULL)
|
(*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
|
||||||
|
|
||||||
#define FILETIME_TO_TIME_T(filetime) \
|
#define FILETIME_TO_TIME_T(filetime) \
|
||||||
(FILETIME_TO_UINT(filetime) / 10000000ULL)
|
(FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
|
||||||
|
|
||||||
#define FILETIME_TO_TIME_NS(filetime, secs) \
|
#define FILETIME_TO_TIME_NS(filetime, secs) \
|
||||||
((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100)
|
((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
|
||||||
|
|
||||||
#define FILETIME_TO_TIMESPEC(ts, filetime) \
|
#define FILETIME_TO_TIMESPEC(ts, filetime) \
|
||||||
do { \
|
do { \
|
||||||
@@ -109,8 +116,8 @@
|
|||||||
|
|
||||||
#define TIME_T_TO_FILETIME(time, filetime_ptr) \
|
#define TIME_T_TO_FILETIME(time, filetime_ptr) \
|
||||||
do { \
|
do { \
|
||||||
uint64_t bigtime = ((uint64_t) ((time) * 10000000ULL)) + \
|
uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) + \
|
||||||
116444736000000000ULL; \
|
(uint64_t) 116444736 * BILLIONu; \
|
||||||
(filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \
|
(filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \
|
||||||
(filetime_ptr)->dwHighDateTime = bigtime >> 32; \
|
(filetime_ptr)->dwHighDateTime = bigtime >> 32; \
|
||||||
} while(0)
|
} while(0)
|
||||||
@@ -326,12 +333,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
|||||||
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
|
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
|
||||||
sizeof(WCHAR);
|
sizeof(WCHAR);
|
||||||
|
|
||||||
/* Real symlinks can contain pretty much everything, but the only thing */
|
/* Real symlinks can contain pretty much everything, but the only thing we
|
||||||
/* we really care about is undoing the implicit conversion to an NT */
|
* really care about is undoing the implicit conversion to an NT namespaced
|
||||||
/* namespaced path that CreateSymbolicLink will perform on absolute */
|
* path that CreateSymbolicLink will perform on absolute paths. If the path
|
||||||
/* paths. If the path is win32-namespaced then the user must have */
|
* is win32-namespaced then the user must have explicitly made it so, and
|
||||||
/* explicitly made it so, and we better just return the unmodified */
|
* we better just return the unmodified reparse data. */
|
||||||
/* reparse data. */
|
|
||||||
if (w_target_len >= 4 &&
|
if (w_target_len >= 4 &&
|
||||||
w_target[0] == L'\\' &&
|
w_target[0] == L'\\' &&
|
||||||
w_target[1] == L'?' &&
|
w_target[1] == L'?' &&
|
||||||
@@ -352,8 +358,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
|||||||
(w_target[5] == L'N' || w_target[5] == L'n') &&
|
(w_target[5] == L'N' || w_target[5] == L'n') &&
|
||||||
(w_target[6] == L'C' || w_target[6] == L'c') &&
|
(w_target[6] == L'C' || w_target[6] == L'c') &&
|
||||||
w_target[7] == L'\\') {
|
w_target[7] == L'\\') {
|
||||||
/* \??\UNC\<server>\<share>\ - make sure the final path looks like */
|
/* \??\UNC\<server>\<share>\ - make sure the final path looks like
|
||||||
/* \\<server>\<share>\ */
|
* \\<server>\<share>\ */
|
||||||
w_target += 6;
|
w_target += 6;
|
||||||
w_target[0] = L'\\';
|
w_target[0] = L'\\';
|
||||||
w_target_len -= 6;
|
w_target_len -= 6;
|
||||||
@@ -368,11 +374,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
|||||||
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
|
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
|
||||||
sizeof(WCHAR);
|
sizeof(WCHAR);
|
||||||
|
|
||||||
/* Only treat junctions that look like \??\<drive>:\ as symlink. */
|
/* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
|
||||||
/* Junctions can also be used as mount points, like \??\Volume{<guid>}, */
|
* can also be used as mount points, like \??\Volume{<guid>}, but that's
|
||||||
/* but that's confusing for programs since they wouldn't be able to */
|
* confusing for programs since they wouldn't be able to actually
|
||||||
/* actually understand such a path when returned by uv_readlink(). */
|
* understand such a path when returned by uv_readlink(). UNC paths are
|
||||||
/* UNC paths are never valid for junctions so we don't care about them. */
|
* never valid for junctions so we don't care about them. */
|
||||||
if (!(w_target_len >= 6 &&
|
if (!(w_target_len >= 6 &&
|
||||||
w_target[0] == L'\\' &&
|
w_target[0] == L'\\' &&
|
||||||
w_target[1] == L'?' &&
|
w_target[1] == L'?' &&
|
||||||
@@ -409,8 +415,8 @@ void fs__open(uv_fs_t* req) {
|
|||||||
int fd, current_umask;
|
int fd, current_umask;
|
||||||
int flags = req->fs.info.file_flags;
|
int flags = req->fs.info.file_flags;
|
||||||
|
|
||||||
/* Obtain the active umask. umask() never fails and returns the previous */
|
/* Obtain the active umask. umask() never fails and returns the previous
|
||||||
/* umask. */
|
* umask. */
|
||||||
current_umask = umask(0);
|
current_umask = umask(0);
|
||||||
umask(current_umask);
|
umask(current_umask);
|
||||||
|
|
||||||
@@ -502,6 +508,33 @@ void fs__open(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & UV_FS_O_DIRECT) {
|
if (flags & UV_FS_O_DIRECT) {
|
||||||
|
/*
|
||||||
|
* FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.
|
||||||
|
* Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.
|
||||||
|
*
|
||||||
|
* FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:
|
||||||
|
*
|
||||||
|
* FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
|
||||||
|
* FILE_WRITE_DATA |
|
||||||
|
* FILE_WRITE_ATTRIBUTES |
|
||||||
|
* FILE_WRITE_EA |
|
||||||
|
* FILE_APPEND_DATA |
|
||||||
|
* SYNCHRONIZE
|
||||||
|
*
|
||||||
|
* Note: Appends are also permitted by FILE_WRITE_DATA.
|
||||||
|
*
|
||||||
|
* In order for direct writes and direct appends to succeed, we therefore
|
||||||
|
* exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise
|
||||||
|
* fail if the user's sole permission is a direct append, since this
|
||||||
|
* particular combination is invalid.
|
||||||
|
*/
|
||||||
|
if (access & FILE_APPEND_DATA) {
|
||||||
|
if (access & FILE_WRITE_DATA) {
|
||||||
|
access &= ~FILE_APPEND_DATA;
|
||||||
|
} else {
|
||||||
|
goto einval;
|
||||||
|
}
|
||||||
|
}
|
||||||
attributes |= FILE_FLAG_NO_BUFFERING;
|
attributes |= FILE_FLAG_NO_BUFFERING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,8 +563,8 @@ void fs__open(uv_fs_t* req) {
|
|||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
|
if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
|
||||||
!(flags & UV_FS_O_EXCL)) {
|
!(flags & UV_FS_O_EXCL)) {
|
||||||
/* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */
|
/* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
|
||||||
/* specified, it means the path referred to a directory. */
|
* specified, it means the path referred to a directory. */
|
||||||
SET_REQ_UV_ERROR(req, UV_EISDIR, error);
|
SET_REQ_UV_ERROR(req, UV_EISDIR, error);
|
||||||
} else {
|
} else {
|
||||||
SET_REQ_WIN32_ERROR(req, GetLastError());
|
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||||
@@ -756,9 +789,9 @@ void fs__unlink(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
/* Do not allow deletion of directories, unless it is a symlink. When */
|
/* Do not allow deletion of directories, unless it is a symlink. When the
|
||||||
/* the path refers to a non-symlink directory, report EPERM as mandated */
|
* path refers to a non-symlink directory, report EPERM as mandated by
|
||||||
/* by POSIX.1. */
|
* POSIX.1. */
|
||||||
|
|
||||||
/* Check if it is a reparse point. If it's not, it's a normal directory. */
|
/* Check if it is a reparse point. If it's not, it's a normal directory. */
|
||||||
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||||
@@ -767,8 +800,8 @@ void fs__unlink(uv_fs_t* req) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the reparse point and check if it is a valid symlink. */
|
/* Read the reparse point and check if it is a valid symlink. If not, don't
|
||||||
/* If not, don't unlink. */
|
* unlink. */
|
||||||
if (fs__readlink_handle(handle, NULL, NULL) < 0) {
|
if (fs__readlink_handle(handle, NULL, NULL) < 0) {
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
if (error == ERROR_SYMLINK_NOT_SUPPORTED)
|
if (error == ERROR_SYMLINK_NOT_SUPPORTED)
|
||||||
@@ -783,9 +816,8 @@ void fs__unlink(uv_fs_t* req) {
|
|||||||
/* Remove read-only attribute */
|
/* Remove read-only attribute */
|
||||||
FILE_BASIC_INFORMATION basic = { 0 };
|
FILE_BASIC_INFORMATION basic = { 0 };
|
||||||
|
|
||||||
basic.FileAttributes = info.dwFileAttributes
|
basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |
|
||||||
& ~(FILE_ATTRIBUTE_READONLY)
|
FILE_ATTRIBUTE_ARCHIVE;
|
||||||
| FILE_ATTRIBUTE_ARCHIVE;
|
|
||||||
|
|
||||||
status = pNtSetInformationFile(handle,
|
status = pNtSetInformationFile(handle,
|
||||||
&iosb,
|
&iosb,
|
||||||
@@ -1196,7 +1228,7 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
|
|||||||
|
|
||||||
/* st_blocks contains the on-disk allocation size in 512-byte units. */
|
/* st_blocks contains the on-disk allocation size in 512-byte units. */
|
||||||
statbuf->st_blocks =
|
statbuf->st_blocks =
|
||||||
file_info.StandardInformation.AllocationSize.QuadPart >> 9ULL;
|
(uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;
|
||||||
|
|
||||||
statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
|
statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
|
||||||
|
|
||||||
@@ -1490,6 +1522,7 @@ static void fs__chmod(uv_fs_t* req) {
|
|||||||
|
|
||||||
static void fs__fchmod(uv_fs_t* req) {
|
static void fs__fchmod(uv_fs_t* req) {
|
||||||
int fd = req->file.fd;
|
int fd = req->file.fd;
|
||||||
|
int clear_archive_flag;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
NTSTATUS nt_status;
|
NTSTATUS nt_status;
|
||||||
IO_STATUS_BLOCK io_status;
|
IO_STATUS_BLOCK io_status;
|
||||||
@@ -1497,7 +1530,11 @@ static void fs__fchmod(uv_fs_t* req) {
|
|||||||
|
|
||||||
VERIFY_FD(fd, req);
|
VERIFY_FD(fd, req);
|
||||||
|
|
||||||
handle = uv__get_osfhandle(fd);
|
handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
|
SET_REQ_WIN32_ERROR(req, GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nt_status = pNtQueryInformationFile(handle,
|
nt_status = pNtQueryInformationFile(handle,
|
||||||
&io_status,
|
&io_status,
|
||||||
@@ -1507,7 +1544,27 @@ static void fs__fchmod(uv_fs_t* req) {
|
|||||||
|
|
||||||
if (!NT_SUCCESS(nt_status)) {
|
if (!NT_SUCCESS(nt_status)) {
|
||||||
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
||||||
return;
|
goto fchmod_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test if the Archive attribute is cleared */
|
||||||
|
if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
|
||||||
|
/* Set Archive flag, otherwise setting or clearing the read-only
|
||||||
|
flag will not work */
|
||||||
|
file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
nt_status = pNtSetInformationFile(handle,
|
||||||
|
&io_status,
|
||||||
|
&file_info,
|
||||||
|
sizeof file_info,
|
||||||
|
FileBasicInformation);
|
||||||
|
if (!NT_SUCCESS(nt_status)) {
|
||||||
|
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
||||||
|
goto fchmod_cleanup;
|
||||||
|
}
|
||||||
|
/* Remeber to clear the flag later on */
|
||||||
|
clear_archive_flag = 1;
|
||||||
|
} else {
|
||||||
|
clear_archive_flag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req->fs.info.mode & _S_IWRITE) {
|
if (req->fs.info.mode & _S_IWRITE) {
|
||||||
@@ -1524,10 +1581,28 @@ static void fs__fchmod(uv_fs_t* req) {
|
|||||||
|
|
||||||
if (!NT_SUCCESS(nt_status)) {
|
if (!NT_SUCCESS(nt_status)) {
|
||||||
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
||||||
return;
|
goto fchmod_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear_archive_flag) {
|
||||||
|
file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
if (file_info.FileAttributes == 0) {
|
||||||
|
file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
}
|
||||||
|
nt_status = pNtSetInformationFile(handle,
|
||||||
|
&io_status,
|
||||||
|
&file_info,
|
||||||
|
sizeof file_info,
|
||||||
|
FileBasicInformation);
|
||||||
|
if (!NT_SUCCESS(nt_status)) {
|
||||||
|
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
|
||||||
|
goto fchmod_cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_REQ_SUCCESS(req);
|
SET_REQ_SUCCESS(req);
|
||||||
|
fchmod_cleanup:
|
||||||
|
CloseHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1787,17 +1862,13 @@ static void fs__symlink(uv_fs_t* req) {
|
|||||||
fs__create_junction(req, pathw, new_pathw);
|
fs__create_junction(req, pathw, new_pathw);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!pCreateSymbolicLinkW) {
|
|
||||||
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
|
if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
|
||||||
flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
|
flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
|
||||||
else
|
else
|
||||||
flags = uv__file_symlink_usermode_flag;
|
flags = uv__file_symlink_usermode_flag;
|
||||||
|
|
||||||
if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) {
|
if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
|
||||||
SET_REQ_RESULT(req, 0);
|
SET_REQ_RESULT(req, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1848,13 +1919,13 @@ static void fs__readlink(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
||||||
int r;
|
int r;
|
||||||
DWORD w_realpath_len;
|
DWORD w_realpath_len;
|
||||||
WCHAR* w_realpath_ptr = NULL;
|
WCHAR* w_realpath_ptr = NULL;
|
||||||
WCHAR* w_realpath_buf;
|
WCHAR* w_realpath_buf;
|
||||||
|
|
||||||
w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
|
w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
|
||||||
if (w_realpath_len == 0) {
|
if (w_realpath_len == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1866,10 +1937,8 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
|||||||
}
|
}
|
||||||
w_realpath_ptr = w_realpath_buf;
|
w_realpath_ptr = w_realpath_buf;
|
||||||
|
|
||||||
if (pGetFinalPathNameByHandleW(handle,
|
if (GetFinalPathNameByHandleW(
|
||||||
w_realpath_ptr,
|
handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
|
||||||
w_realpath_len,
|
|
||||||
VOLUME_NAME_DOS) == 0) {
|
|
||||||
uv__free(w_realpath_buf);
|
uv__free(w_realpath_buf);
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1901,11 +1970,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
|
|||||||
static void fs__realpath(uv_fs_t* req) {
|
static void fs__realpath(uv_fs_t* req) {
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
|
||||||
if (!pGetFinalPathNameByHandleW) {
|
|
||||||
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = CreateFileW(req->file.pathw,
|
handle = CreateFileW(req->file.pathw,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -1940,6 +2004,10 @@ static void fs__fchown(uv_fs_t* req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fs__lchown(uv_fs_t* req) {
|
||||||
|
req->result = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void uv__fs_work(struct uv__work* w) {
|
static void uv__fs_work(struct uv__work* w) {
|
||||||
uv_fs_t* req;
|
uv_fs_t* req;
|
||||||
|
|
||||||
@@ -1977,6 +2045,7 @@ static void uv__fs_work(struct uv__work* w) {
|
|||||||
XX(REALPATH, realpath)
|
XX(REALPATH, realpath)
|
||||||
XX(CHOWN, chown)
|
XX(CHOWN, chown)
|
||||||
XX(FCHOWN, fchown);
|
XX(FCHOWN, fchown);
|
||||||
|
XX(LCHOWN, lchown);
|
||||||
default:
|
default:
|
||||||
assert(!"bad uv_fs_type");
|
assert(!"bad uv_fs_type");
|
||||||
}
|
}
|
||||||
@@ -2262,6 +2331,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
|
||||||
|
uv_gid_t gid, uv_fs_cb cb) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
INIT(UV_FS_LCHOWN);
|
||||||
|
err = fs__capture_path(req, path, NULL, cb != NULL);
|
||||||
|
if (err) {
|
||||||
|
return uv_translate_sys_error(err);
|
||||||
|
}
|
||||||
|
POST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "req-inl.h"
|
#include "req-inl.h"
|
||||||
|
#include "idna.h"
|
||||||
|
|
||||||
/* EAI_* constants. */
|
/* EAI_* constants. */
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@@ -71,8 +72,8 @@ int uv__getaddrinfo_translate_error(int sys_err) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* adjust size value to be multiple of 4. Use to keep pointer aligned */
|
/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
|
||||||
/* Do we need different versions of this for different architectures? */
|
* Do we need different versions of this for different architectures? */
|
||||||
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
|
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
|
||||||
|
|
||||||
#ifndef NDIS_IF_MAX_STRING_SIZE
|
#ifndef NDIS_IF_MAX_STRING_SIZE
|
||||||
@@ -124,8 +125,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req->retcode == 0) {
|
if (req->retcode == 0) {
|
||||||
/* convert addrinfoW to addrinfo */
|
/* Convert addrinfoW to addrinfo. First calculate required length. */
|
||||||
/* first calculate required length */
|
|
||||||
addrinfow_ptr = req->addrinfow;
|
addrinfow_ptr = req->addrinfow;
|
||||||
while (addrinfow_ptr != NULL) {
|
while (addrinfow_ptr != NULL) {
|
||||||
addrinfo_len += addrinfo_struct_len +
|
addrinfo_len += addrinfo_struct_len +
|
||||||
@@ -260,11 +260,13 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
const char* node,
|
const char* node,
|
||||||
const char* service,
|
const char* service,
|
||||||
const struct addrinfo* hints) {
|
const struct addrinfo* hints) {
|
||||||
|
char hostname_ascii[256];
|
||||||
int nodesize = 0;
|
int nodesize = 0;
|
||||||
int servicesize = 0;
|
int servicesize = 0;
|
||||||
int hintssize = 0;
|
int hintssize = 0;
|
||||||
char* alloc_ptr = NULL;
|
char* alloc_ptr = NULL;
|
||||||
int err;
|
int err;
|
||||||
|
long rc;
|
||||||
|
|
||||||
if (req == NULL || (node == NULL && service == NULL)) {
|
if (req == NULL || (node == NULL && service == NULL)) {
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
@@ -278,12 +280,19 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
|
|
||||||
/* calculate required memory size for all input values */
|
/* calculate required memory size for all input values */
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, node, -1, NULL, 0) *
|
rc = uv__idna_toascii(node,
|
||||||
sizeof(WCHAR));
|
node + strlen(node),
|
||||||
|
hostname_ascii,
|
||||||
|
hostname_ascii + sizeof(hostname_ascii));
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
|
||||||
|
-1, NULL, 0) * sizeof(WCHAR));
|
||||||
if (nodesize == 0) {
|
if (nodesize == 0) {
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
node = hostname_ascii;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (service != NULL) {
|
if (service != NULL) {
|
||||||
@@ -313,8 +322,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
/* save alloc_ptr now so we can free if error */
|
/* save alloc_ptr now so we can free if error */
|
||||||
req->alloc = (void*)alloc_ptr;
|
req->alloc = (void*)alloc_ptr;
|
||||||
|
|
||||||
/* convert node string to UTF16 into allocated memory and save pointer in */
|
/* Convert node string to UTF16 into allocated memory and save pointer in the
|
||||||
/* the request. */
|
* request. */
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
req->node = (WCHAR*)alloc_ptr;
|
req->node = (WCHAR*)alloc_ptr;
|
||||||
if (MultiByteToWideChar(CP_UTF8,
|
if (MultiByteToWideChar(CP_UTF8,
|
||||||
@@ -331,8 +340,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
req->node = NULL;
|
req->node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert service string to UTF16 into allocated memory and save pointer */
|
/* Convert service string to UTF16 into allocated memory and save pointer in
|
||||||
/* in the req. */
|
* the req. */
|
||||||
if (service != NULL) {
|
if (service != NULL) {
|
||||||
req->service = (WCHAR*)alloc_ptr;
|
req->service = (WCHAR*)alloc_ptr;
|
||||||
if (MultiByteToWideChar(CP_UTF8,
|
if (MultiByteToWideChar(CP_UTF8,
|
||||||
@@ -369,6 +378,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
|||||||
if (getaddrinfo_cb) {
|
if (getaddrinfo_cb) {
|
||||||
uv__work_submit(loop,
|
uv__work_submit(loop,
|
||||||
&req->work_req,
|
&req->work_req,
|
||||||
|
UV__WORK_SLOW_IO,
|
||||||
uv__getaddrinfo_work,
|
uv__getaddrinfo_work,
|
||||||
uv__getaddrinfo_done);
|
uv__getaddrinfo_done);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -392,21 +402,15 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
|
|||||||
DWORD bufsize;
|
DWORD bufsize;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
uv__once_init();
|
|
||||||
|
|
||||||
if (buffer == NULL || size == NULL || *size == 0)
|
if (buffer == NULL || size == NULL || *size == 0)
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
if (pConvertInterfaceIndexToLuid == NULL)
|
r = ConvertInterfaceIndexToLuid(ifindex, &luid);
|
||||||
return UV_ENOSYS;
|
|
||||||
r = pConvertInterfaceIndexToLuid(ifindex, &luid);
|
|
||||||
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return uv_translate_sys_error(r);
|
return uv_translate_sys_error(r);
|
||||||
|
|
||||||
if (pConvertInterfaceLuidToNameW == NULL)
|
r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
|
||||||
return UV_ENOSYS;
|
|
||||||
r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
|
|
||||||
|
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return uv_translate_sys_error(r);
|
return uv_translate_sys_error(r);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ static void uv__getnameinfo_work(struct uv__work* w) {
|
|||||||
uv_getnameinfo_t* req;
|
uv_getnameinfo_t* req;
|
||||||
WCHAR host[NI_MAXHOST];
|
WCHAR host[NI_MAXHOST];
|
||||||
WCHAR service[NI_MAXSERV];
|
WCHAR service[NI_MAXSERV];
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
req = container_of(w, uv_getnameinfo_t, work_req);
|
req = container_of(w, uv_getnameinfo_t, work_req);
|
||||||
if (GetNameInfoW((struct sockaddr*)&req->storage,
|
if (GetNameInfoW((struct sockaddr*)&req->storage,
|
||||||
@@ -53,27 +53,34 @@ static void uv__getnameinfo_work(struct uv__work* w) {
|
|||||||
ARRAY_SIZE(service),
|
ARRAY_SIZE(service),
|
||||||
req->flags)) {
|
req->flags)) {
|
||||||
ret = WSAGetLastError();
|
ret = WSAGetLastError();
|
||||||
|
req->retcode = uv__getaddrinfo_translate_error(ret);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
req->retcode = uv__getaddrinfo_translate_error(ret);
|
|
||||||
|
|
||||||
/* convert results to UTF-8 */
|
ret = WideCharToMultiByte(CP_UTF8,
|
||||||
WideCharToMultiByte(CP_UTF8,
|
0,
|
||||||
0,
|
host,
|
||||||
host,
|
-1,
|
||||||
-1,
|
req->host,
|
||||||
req->host,
|
sizeof(req->host),
|
||||||
sizeof(req->host),
|
NULL,
|
||||||
NULL,
|
NULL);
|
||||||
NULL);
|
if (ret == 0) {
|
||||||
|
req->retcode = uv_translate_sys_error(GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WideCharToMultiByte(CP_UTF8,
|
ret = WideCharToMultiByte(CP_UTF8,
|
||||||
0,
|
0,
|
||||||
service,
|
service,
|
||||||
-1,
|
-1,
|
||||||
req->service,
|
req->service,
|
||||||
sizeof(req->service),
|
sizeof(req->service),
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (ret == 0) {
|
||||||
|
req->retcode = uv_translate_sys_error(GetLastError());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -138,6 +145,7 @@ int uv_getnameinfo(uv_loop_t* loop,
|
|||||||
if (getnameinfo_cb) {
|
if (getnameinfo_cb) {
|
||||||
uv__work_submit(loop,
|
uv__work_submit(loop,
|
||||||
&req->work_req,
|
&req->work_req,
|
||||||
|
UV__WORK_SLOW_IO,
|
||||||
uv__getnameinfo_work,
|
uv__getnameinfo_work,
|
||||||
uv__getnameinfo_done);
|
uv__getnameinfo_done);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#define DECREASE_ACTIVE_COUNT(loop, handle) \
|
#define DECREASE_ACTIVE_COUNT(loop, handle) \
|
||||||
do { \
|
do { \
|
||||||
if (--(handle)->activecnt == 0 && \
|
if (--(handle)->activecnt == 0 && \
|
||||||
!((handle)->flags & UV__HANDLE_CLOSING)) { \
|
!((handle)->flags & UV_HANDLE_CLOSING)) { \
|
||||||
uv__handle_stop((handle)); \
|
uv__handle_stop((handle)); \
|
||||||
} \
|
} \
|
||||||
assert((handle)->activecnt >= 0); \
|
assert((handle)->activecnt >= 0); \
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
assert(handle->reqs_pending > 0); \
|
assert(handle->reqs_pending > 0); \
|
||||||
handle->reqs_pending--; \
|
handle->reqs_pending--; \
|
||||||
\
|
\
|
||||||
if (handle->flags & UV__HANDLE_CLOSING && \
|
if (handle->flags & UV_HANDLE_CLOSING && \
|
||||||
handle->reqs_pending == 0) { \
|
handle->reqs_pending == 0) { \
|
||||||
uv_want_endgame(loop, (uv_handle_t*)handle); \
|
uv_want_endgame(loop, (uv_handle_t*)handle); \
|
||||||
} \
|
} \
|
||||||
@@ -62,14 +62,14 @@
|
|||||||
|
|
||||||
#define uv__handle_closing(handle) \
|
#define uv__handle_closing(handle) \
|
||||||
do { \
|
do { \
|
||||||
assert(!((handle)->flags & UV__HANDLE_CLOSING)); \
|
assert(!((handle)->flags & UV_HANDLE_CLOSING)); \
|
||||||
\
|
\
|
||||||
if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \
|
if (!(((handle)->flags & UV_HANDLE_ACTIVE) && \
|
||||||
((handle)->flags & UV__HANDLE_REF))) \
|
((handle)->flags & UV_HANDLE_REF))) \
|
||||||
uv__active_handle_add((uv_handle_t*) (handle)); \
|
uv__active_handle_add((uv_handle_t*) (handle)); \
|
||||||
\
|
\
|
||||||
(handle)->flags |= UV__HANDLE_CLOSING; \
|
(handle)->flags |= UV_HANDLE_CLOSING; \
|
||||||
(handle)->flags &= ~UV__HANDLE_ACTIVE; \
|
(handle)->flags &= ~UV_HANDLE_ACTIVE; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
@@ -126,7 +126,8 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case UV_TIMER:
|
case UV_TIMER:
|
||||||
uv_timer_endgame(loop, (uv_timer_t*) handle);
|
uv__timer_close((uv_timer_t*) handle);
|
||||||
|
uv__handle_close(handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UV_PREPARE:
|
case UV_PREPARE:
|
||||||
@@ -164,10 +165,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
|
|||||||
|
|
||||||
INLINE static HANDLE uv__get_osfhandle(int fd)
|
INLINE static HANDLE uv__get_osfhandle(int fd)
|
||||||
{
|
{
|
||||||
/* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */
|
/* _get_osfhandle() raises an assert in debug builds if the FD is invalid.
|
||||||
/* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */
|
* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for
|
||||||
/* for invalid FDs in release builds (or if you let the assert continue). */
|
* invalid FDs in release builds (or if you let the assert continue). So this
|
||||||
/* So this wrapper function disables asserts when calling _get_osfhandle. */
|
* wrapper function disables asserts when calling _get_osfhandle. */
|
||||||
|
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
UV_BEGIN_DISABLE_CRT_ASSERT();
|
UV_BEGIN_DISABLE_CRT_ASSERT();
|
||||||
|
|||||||
@@ -59,15 +59,15 @@ uv_handle_type uv_guess_handle(uv_file file) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_is_active(const uv_handle_t* handle) {
|
int uv_is_active(const uv_handle_t* handle) {
|
||||||
return (handle->flags & UV__HANDLE_ACTIVE) &&
|
return (handle->flags & UV_HANDLE_ACTIVE) &&
|
||||||
!(handle->flags & UV__HANDLE_CLOSING);
|
!(handle->flags & UV_HANDLE_CLOSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
||||||
uv_loop_t* loop = handle->loop;
|
uv_loop_t* loop = handle->loop;
|
||||||
|
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
assert(0);
|
assert(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -150,10 +150,14 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_is_closing(const uv_handle_t* handle) {
|
int uv_is_closing(const uv_handle_t* handle) {
|
||||||
return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED));
|
return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uv_os_fd_t uv_get_osfhandle(int fd) {
|
uv_os_fd_t uv_get_osfhandle(int fd) {
|
||||||
return uv__get_osfhandle(fd);
|
return uv__get_osfhandle(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uv_open_osfhandle(uv_os_fd_t os_fd) {
|
||||||
|
return _open_osfhandle((intptr_t) os_fd, 0);
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "../uv-common.h"
|
#include "../uv-common.h"
|
||||||
|
|
||||||
#include "tree.h"
|
#include "uv/tree.h"
|
||||||
#include "winapi.h"
|
#include "winapi.h"
|
||||||
#include "winsock.h"
|
#include "winsock.h"
|
||||||
|
|
||||||
@@ -61,78 +61,20 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
|
|||||||
#define UV_END_DISABLE_CRT_ASSERT()
|
#define UV_END_DISABLE_CRT_ASSERT()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Handles
|
|
||||||
* (also see handle-inl.h)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Used by all handles. */
|
|
||||||
#define UV_HANDLE_CLOSED 0x00000002
|
|
||||||
#define UV_HANDLE_ENDGAME_QUEUED 0x00000008
|
|
||||||
|
|
||||||
/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */
|
|
||||||
/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */
|
|
||||||
/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */
|
|
||||||
/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */
|
|
||||||
|
|
||||||
/* Used by streams and UDP handles. */
|
|
||||||
#define UV_HANDLE_READING 0x00000100
|
|
||||||
#define UV_HANDLE_BOUND 0x00000200
|
|
||||||
#define UV_HANDLE_LISTENING 0x00000800
|
|
||||||
#define UV_HANDLE_CONNECTION 0x00001000
|
|
||||||
#define UV_HANDLE_READABLE 0x00008000
|
|
||||||
#define UV_HANDLE_WRITABLE 0x00010000
|
|
||||||
#define UV_HANDLE_READ_PENDING 0x00020000
|
|
||||||
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000
|
|
||||||
#define UV_HANDLE_ZERO_READ 0x00080000
|
|
||||||
#define UV_HANDLE_EMULATE_IOCP 0x00100000
|
|
||||||
#define UV_HANDLE_BLOCKING_WRITES 0x00200000
|
|
||||||
#define UV_HANDLE_CANCELLATION_PENDING 0x00400000
|
|
||||||
|
|
||||||
/* Used by uv_tcp_t and uv_udp_t handles */
|
|
||||||
#define UV_HANDLE_IPV6 0x01000000
|
|
||||||
|
|
||||||
/* Only used by uv_tcp_t handles. */
|
|
||||||
#define UV_HANDLE_TCP_NODELAY 0x02000000
|
|
||||||
#define UV_HANDLE_TCP_KEEPALIVE 0x04000000
|
|
||||||
#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000
|
|
||||||
#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000
|
|
||||||
#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000
|
|
||||||
#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000
|
|
||||||
|
|
||||||
/* Only used by uv_pipe_t handles. */
|
|
||||||
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000
|
|
||||||
#define UV_HANDLE_PIPESERVER 0x02000000
|
|
||||||
#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000
|
|
||||||
|
|
||||||
/* Only used by uv_tty_t handles. */
|
|
||||||
#define UV_HANDLE_TTY_READABLE 0x01000000
|
|
||||||
#define UV_HANDLE_TTY_RAW 0x02000000
|
|
||||||
#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000
|
|
||||||
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000
|
|
||||||
|
|
||||||
/* Only used by uv_poll_t handles. */
|
|
||||||
#define UV_HANDLE_POLL_SLOW 0x02000000
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Requests: see req-inl.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Streams: see stream-inl.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP
|
* TCP
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UV__IPC_SOCKET_XFER_NONE = 0,
|
||||||
|
UV__IPC_SOCKET_XFER_TCP_CONNECTION,
|
||||||
|
UV__IPC_SOCKET_XFER_TCP_SERVER
|
||||||
|
} uv__ipc_socket_xfer_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
WSAPROTOCOL_INFOW socket_info;
|
WSAPROTOCOL_INFOW socket_info;
|
||||||
int delayed_error;
|
uint32_t delayed_error;
|
||||||
} uv__ipc_socket_info_ex;
|
} uv__ipc_socket_xfer_info_t;
|
||||||
|
|
||||||
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
|
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
|
||||||
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
|
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
|
||||||
@@ -154,11 +96,13 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
|
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
|
||||||
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
|
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
|
||||||
|
|
||||||
int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
|
int uv__tcp_xfer_export(uv_tcp_t* handle,
|
||||||
int tcp_connection);
|
int pid,
|
||||||
|
uv__ipc_socket_xfer_type_t* xfer_type,
|
||||||
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
|
uv__ipc_socket_xfer_info_t* xfer_info);
|
||||||
LPWSAPROTOCOL_INFOW protocol_info);
|
int uv__tcp_xfer_import(uv_tcp_t* tcp,
|
||||||
|
uv__ipc_socket_xfer_type_t xfer_type,
|
||||||
|
uv__ipc_socket_xfer_info_t* xfer_info);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -182,14 +126,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
|
|||||||
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
|
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
|
||||||
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
|
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
|
||||||
uv_read_cb read_cb);
|
uv_read_cb read_cb);
|
||||||
int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
|
void uv__pipe_read_stop(uv_pipe_t* handle);
|
||||||
const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
|
int uv__pipe_write(uv_loop_t* loop,
|
||||||
int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
|
uv_write_t* req,
|
||||||
const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle,
|
uv_pipe_t* handle,
|
||||||
uv_write_cb cb);
|
const uv_buf_t bufs[],
|
||||||
void uv__pipe_pause_read(uv_pipe_t* handle);
|
size_t nbufs,
|
||||||
void uv__pipe_unpause_read(uv_pipe_t* handle);
|
uv_stream_t* send_handle,
|
||||||
void uv__pipe_stop_read(uv_pipe_t* handle);
|
uv_write_cb cb);
|
||||||
|
|
||||||
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
|
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
|
||||||
uv_req_t* req);
|
uv_req_t* req);
|
||||||
@@ -251,15 +195,6 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);
|
|||||||
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
|
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Timers
|
|
||||||
*/
|
|
||||||
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
|
|
||||||
|
|
||||||
DWORD uv__next_timeout(const uv_loop_t* loop);
|
|
||||||
void uv_process_timers(uv_loop_t* loop);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop watchers
|
* Loop watchers
|
||||||
*/
|
*/
|
||||||
@@ -336,7 +271,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
|
|||||||
void uv__util_init(void);
|
void uv__util_init(void);
|
||||||
|
|
||||||
uint64_t uv__hrtime(double scale);
|
uint64_t uv__hrtime(double scale);
|
||||||
int uv_current_pid(void);
|
|
||||||
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
|
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
|
||||||
int uv__getpwuid_r(uv_passwd_t* pwd);
|
int uv__getpwuid_r(uv_passwd_t* pwd);
|
||||||
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
|
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
|
void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
handle->flags |= UV_HANDLE_CLOSED;
|
handle->flags |= UV_HANDLE_CLOSED;
|
||||||
uv__handle_close(handle);
|
uv__handle_close(handle);
|
||||||
|
|||||||
+648
-484
File diff suppressed because it is too large
Load Diff
@@ -75,7 +75,7 @@ static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
|
|||||||
static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
||||||
uv_req_t* req;
|
uv_req_t* req;
|
||||||
AFD_POLL_INFO* afd_poll_info;
|
AFD_POLL_INFO* afd_poll_info;
|
||||||
DWORD result;
|
int result;
|
||||||
|
|
||||||
/* Find a yet unsubmitted req to submit. */
|
/* Find a yet unsubmitted req to submit. */
|
||||||
if (handle->submitted_events_1 == 0) {
|
if (handle->submitted_events_1 == 0) {
|
||||||
@@ -91,16 +91,16 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
|||||||
handle->mask_events_1 = handle->events;
|
handle->mask_events_1 = handle->events;
|
||||||
handle->mask_events_2 = 0;
|
handle->mask_events_2 = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Just wait until there's an unsubmitted req. */
|
/* Just wait until there's an unsubmitted req. This will happen almost
|
||||||
/* This will happen almost immediately as one of the 2 outstanding */
|
* immediately as one of the 2 outstanding requests is about to return.
|
||||||
/* requests is about to return. When this happens, */
|
* When this happens, uv__fast_poll_process_poll_req will be called, and
|
||||||
/* uv__fast_poll_process_poll_req will be called, and the pending */
|
* the pending events, if needed, will be processed in a subsequent
|
||||||
/* events, if needed, will be processed in a subsequent request. */
|
* request. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setting Exclusive to TRUE makes the other poll request return if there */
|
/* Setting Exclusive to TRUE makes the other poll request return if there is
|
||||||
/* is any. */
|
* any. */
|
||||||
afd_poll_info->Exclusive = TRUE;
|
afd_poll_info->Exclusive = TRUE;
|
||||||
afd_poll_info->NumberOfHandles = 1;
|
afd_poll_info->NumberOfHandles = 1;
|
||||||
afd_poll_info->Timeout.QuadPart = INT64_MAX;
|
afd_poll_info->Timeout.QuadPart = INT64_MAX;
|
||||||
@@ -136,7 +136,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
|||||||
|
|
||||||
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
|
||||||
AFD_POLL_INFO afd_poll_info;
|
AFD_POLL_INFO afd_poll_info;
|
||||||
DWORD result;
|
int result;
|
||||||
|
|
||||||
afd_poll_info.Exclusive = TRUE;
|
afd_poll_info.Exclusive = TRUE;
|
||||||
afd_poll_info.NumberOfHandles = 1;
|
afd_poll_info.NumberOfHandles = 1;
|
||||||
@@ -218,7 +218,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|||||||
if ((handle->events & ~(handle->submitted_events_1 |
|
if ((handle->events & ~(handle->submitted_events_1 |
|
||||||
handle->submitted_events_2)) != 0) {
|
handle->submitted_events_2)) != 0) {
|
||||||
uv__fast_poll_submit_poll_req(loop, handle);
|
uv__fast_poll_submit_poll_req(loop, handle);
|
||||||
} else if ((handle->flags & UV__HANDLE_CLOSING) &&
|
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
|
||||||
handle->submitted_events_1 == 0 &&
|
handle->submitted_events_1 == 0 &&
|
||||||
handle->submitted_events_2 == 0) {
|
handle->submitted_events_2 == 0) {
|
||||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||||
@@ -228,7 +228,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|||||||
|
|
||||||
static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
|
static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
|
||||||
assert(handle->type == UV_POLL);
|
assert(handle->type == UV_POLL);
|
||||||
assert(!(handle->flags & UV__HANDLE_CLOSING));
|
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||||
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
||||||
|
|
||||||
handle->events = events;
|
handle->events = events;
|
||||||
@@ -257,8 +257,8 @@ static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
|||||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* Cancel outstanding poll requests by executing another, unique poll */
|
/* Cancel outstanding poll requests by executing another, unique poll
|
||||||
/* request that forces the outstanding ones to return. */
|
* request that forces the outstanding ones to return. */
|
||||||
return uv__fast_poll_cancel_poll_req(loop, handle);
|
return uv__fast_poll_cancel_poll_req(loop, handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,9 +316,8 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
|
|||||||
return INVALID_SOCKET;
|
return INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we didn't (try) to create a peer socket yet, try to make one. Don't */
|
/* If we didn't (try) to create a peer socket yet, try to make one. Don't try
|
||||||
/* try again if the peer socket creation failed earlier for the same */
|
* again if the peer socket creation failed earlier for the same protocol. */
|
||||||
/* protocol. */
|
|
||||||
peer_socket = loop->poll_peer_sockets[index];
|
peer_socket = loop->poll_peer_sockets[index];
|
||||||
if (peer_socket == 0) {
|
if (peer_socket == 0) {
|
||||||
peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
|
peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
|
||||||
@@ -357,8 +356,8 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
|
|||||||
efds.fd_count = 0;
|
efds.fd_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the select() time out after 3 minutes. If select() hangs because */
|
/* Make the select() time out after 3 minutes. If select() hangs because the
|
||||||
/* the user closed the socket, we will at least not hang indefinitely. */
|
* user closed the socket, we will at least not hang indefinitely. */
|
||||||
timeout.tv_sec = 3 * 60;
|
timeout.tv_sec = 3 * 60;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
@@ -462,7 +461,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|||||||
if ((handle->events & ~(handle->submitted_events_1 |
|
if ((handle->events & ~(handle->submitted_events_1 |
|
||||||
handle->submitted_events_2)) != 0) {
|
handle->submitted_events_2)) != 0) {
|
||||||
uv__slow_poll_submit_poll_req(loop, handle);
|
uv__slow_poll_submit_poll_req(loop, handle);
|
||||||
} else if ((handle->flags & UV__HANDLE_CLOSING) &&
|
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
|
||||||
handle->submitted_events_1 == 0 &&
|
handle->submitted_events_1 == 0 &&
|
||||||
handle->submitted_events_2 == 0) {
|
handle->submitted_events_2 == 0) {
|
||||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||||
@@ -472,7 +471,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
|
|||||||
|
|
||||||
static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
|
static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
|
||||||
assert(handle->type == UV_POLL);
|
assert(handle->type == UV_POLL);
|
||||||
assert(!(handle->flags & UV__HANDLE_CLOSING));
|
assert(!(handle->flags & UV_HANDLE_CLOSING));
|
||||||
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
|
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
|
||||||
|
|
||||||
handle->events = events;
|
handle->events = events;
|
||||||
@@ -522,10 +521,10 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
|||||||
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
|
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
|
||||||
return uv_translate_sys_error(WSAGetLastError());
|
return uv_translate_sys_error(WSAGetLastError());
|
||||||
|
|
||||||
/* Try to obtain a base handle for the socket. This increases this chances */
|
/* Try to obtain a base handle for the socket. This increases this chances that
|
||||||
/* that we find an AFD handle and are able to use the fast poll mechanism. */
|
* we find an AFD handle and are able to use the fast poll mechanism. This will
|
||||||
/* This will always fail on windows XP/2k3, since they don't support the */
|
* always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE
|
||||||
/* SIO_BASE_HANDLE ioctl. */
|
* ioctl. */
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
base_socket = INVALID_SOCKET;
|
base_socket = INVALID_SOCKET;
|
||||||
#endif
|
#endif
|
||||||
@@ -557,9 +556,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
|||||||
return uv_translate_sys_error(WSAGetLastError());
|
return uv_translate_sys_error(WSAGetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the peer socket that is needed to enable fast poll. If the returned */
|
/* Get the peer socket that is needed to enable fast poll. If the returned
|
||||||
/* value is NULL, the protocol is not implemented by MSAFD and we'll have */
|
* value is NULL, the protocol is not implemented by MSAFD and we'll have to
|
||||||
/* to use slow mode. */
|
* use slow mode. */
|
||||||
peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
|
peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
|
||||||
|
|
||||||
if (peer_socket != INVALID_SOCKET) {
|
if (peer_socket != INVALID_SOCKET) {
|
||||||
@@ -634,7 +633,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
|
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
|
||||||
assert(handle->flags & UV__HANDLE_CLOSING);
|
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
|
|
||||||
assert(handle->submitted_events_1 == 0);
|
assert(handle->submitted_events_1 == 0);
|
||||||
|
|||||||
@@ -103,12 +103,12 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
|||||||
DWORD client_access = 0;
|
DWORD client_access = 0;
|
||||||
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
||||||
int err;
|
int err;
|
||||||
|
int overlap;
|
||||||
|
|
||||||
if (flags & UV_READABLE_PIPE) {
|
if (flags & UV_READABLE_PIPE) {
|
||||||
/* The server needs inbound access too, otherwise CreateNamedPipe() */
|
/* The server needs inbound access too, otherwise CreateNamedPipe() won't
|
||||||
/* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */
|
* give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
|
||||||
/* probe the state of the write buffer when we're trying to shutdown */
|
* state of the write buffer when we're trying to shutdown the pipe. */
|
||||||
/* the pipe. */
|
|
||||||
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
|
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
|
||||||
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
||||||
}
|
}
|
||||||
@@ -131,12 +131,13 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
|||||||
sa.lpSecurityDescriptor = NULL;
|
sa.lpSecurityDescriptor = NULL;
|
||||||
sa.bInheritHandle = TRUE;
|
sa.bInheritHandle = TRUE;
|
||||||
|
|
||||||
|
overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
|
||||||
child_pipe = CreateFileA(pipe_name,
|
child_pipe = CreateFileA(pipe_name,
|
||||||
client_access,
|
client_access,
|
||||||
0,
|
0,
|
||||||
&sa,
|
&sa,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
|
overlap ? FILE_FLAG_OVERLAPPED : 0,
|
||||||
NULL);
|
NULL);
|
||||||
if (child_pipe == INVALID_HANDLE_VALUE) {
|
if (child_pipe == INVALID_HANDLE_VALUE) {
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
@@ -159,8 +160,8 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Do a blocking ConnectNamedPipe. This should not block because we have */
|
/* Do a blocking ConnectNamedPipe. This should not block because we have both
|
||||||
/* both ends of the pipe created. */
|
* ends of the pipe created. */
|
||||||
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
|
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
|
||||||
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
if (GetLastError() != ERROR_PIPE_CONNECTED) {
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
@@ -194,11 +195,11 @@ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
|
|||||||
HANDLE current_process;
|
HANDLE current_process;
|
||||||
|
|
||||||
|
|
||||||
/* _get_osfhandle will sometimes return -2 in case of an error. This seems */
|
/* _get_osfhandle will sometimes return -2 in case of an error. This seems to
|
||||||
/* to happen when fd <= 2 and the process' corresponding stdio handle is */
|
* happen when fd <= 2 and the process' corresponding stdio handle is set to
|
||||||
/* set to NULL. Unfortunately DuplicateHandle will happily duplicate */
|
* NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so
|
||||||
/* (HANDLE) -2, so this situation goes unnoticed until someone tries to */
|
* this situation goes unnoticed until someone tries to use the duplicate.
|
||||||
/* use the duplicate. Therefore we filter out known-invalid handles here. */
|
* Therefore we filter out known-invalid handles here. */
|
||||||
if (handle == INVALID_HANDLE_VALUE ||
|
if (handle == INVALID_HANDLE_VALUE ||
|
||||||
handle == NULL ||
|
handle == NULL ||
|
||||||
handle == (HANDLE) -2) {
|
handle == (HANDLE) -2) {
|
||||||
@@ -284,8 +285,8 @@ int uv__stdio_create(uv_loop_t* loop,
|
|||||||
return ERROR_OUTOFMEMORY;
|
return ERROR_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
|
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean
|
||||||
/* clean up on failure. */
|
* up on failure. */
|
||||||
CHILD_STDIO_COUNT(buffer) = count;
|
CHILD_STDIO_COUNT(buffer) = count;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
|
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
|
||||||
@@ -303,12 +304,12 @@ int uv__stdio_create(uv_loop_t* loop,
|
|||||||
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
|
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
|
||||||
UV_INHERIT_STREAM)) {
|
UV_INHERIT_STREAM)) {
|
||||||
case UV_IGNORE:
|
case UV_IGNORE:
|
||||||
/* Starting a process with no stdin/stout/stderr can confuse it. */
|
/* Starting a process with no stdin/stout/stderr can confuse it. So no
|
||||||
/* So no matter what the user specified, we make sure the first */
|
* matter what the user specified, we make sure the first three FDs are
|
||||||
/* three FDs are always open in their typical modes, e.g. stdin */
|
* always open in their typical modes, e. g. stdin be readable and
|
||||||
/* be readable and stdout/err should be writable. For FDs > 2, don't */
|
* stdout/err should be writable. For FDs > 2, don't do anything - all
|
||||||
/* do anything - all handles in the stdio buffer are initialized with */
|
* handles in the stdio buffer are initialized with.
|
||||||
/* INVALID_HANDLE_VALUE, which should be okay. */
|
* INVALID_HANDLE_VALUE, which should be okay. */
|
||||||
if (i <= 2) {
|
if (i <= 2) {
|
||||||
DWORD access = (i == 0) ? FILE_GENERIC_READ :
|
DWORD access = (i == 0) ? FILE_GENERIC_READ :
|
||||||
FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
||||||
@@ -323,14 +324,14 @@ int uv__stdio_create(uv_loop_t* loop,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case UV_CREATE_PIPE: {
|
case UV_CREATE_PIPE: {
|
||||||
/* Create a pair of two connected pipe ends; one end is turned into */
|
/* Create a pair of two connected pipe ends; one end is turned into an
|
||||||
/* an uv_pipe_t for use by the parent. The other one is given to */
|
* uv_pipe_t for use by the parent. The other one is given to the
|
||||||
/* the child. */
|
* child. */
|
||||||
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
|
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
|
||||||
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
HANDLE child_pipe = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
/* Create a new, connected pipe pair. stdio[i].stream should point */
|
/* Create a new, connected pipe pair. stdio[i]. stream should point to
|
||||||
/* to an uninitialized, but not connected pipe handle. */
|
* an uninitialized, but not connected pipe handle. */
|
||||||
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
|
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
|
||||||
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
|
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
|
||||||
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
|
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
|
||||||
@@ -354,8 +355,8 @@ int uv__stdio_create(uv_loop_t* loop,
|
|||||||
/* Make an inheritable duplicate of the handle. */
|
/* Make an inheritable duplicate of the handle. */
|
||||||
err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
|
err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
|
||||||
if (err) {
|
if (err) {
|
||||||
/* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */
|
/* If fdopt. data. fd is not valid and fd <= 2, then ignore the
|
||||||
/* error. */
|
* error. */
|
||||||
if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
|
if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
|
||||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
|
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
|
||||||
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
|
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
|
||||||
@@ -418,8 +419,8 @@ int uv__stdio_create(uv_loop_t* loop,
|
|||||||
|
|
||||||
if (stream_handle == NULL ||
|
if (stream_handle == NULL ||
|
||||||
stream_handle == INVALID_HANDLE_VALUE) {
|
stream_handle == INVALID_HANDLE_VALUE) {
|
||||||
/* The handle is already closed, or not yet created, or the */
|
/* The handle is already closed, or not yet created, or the stream
|
||||||
/* stream type is not supported. */
|
* type is not supported. */
|
||||||
err = ERROR_NOT_SUPPORTED;
|
err = ERROR_NOT_SUPPORTED;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,8 +360,8 @@ static WCHAR* search_path(const WCHAR *file,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the start of the filename so we can split the directory from the */
|
/* Find the start of the filename so we can split the directory from the
|
||||||
/* name. */
|
* name. */
|
||||||
for (file_name_start = (WCHAR*)file + file_len;
|
for (file_name_start = (WCHAR*)file + file_len;
|
||||||
file_name_start > file
|
file_name_start > file
|
||||||
&& file_name_start[-1] != L'\\'
|
&& file_name_start[-1] != L'\\'
|
||||||
@@ -556,8 +556,8 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
|
|||||||
arg_count++;
|
arg_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust for potential quotes. Also assume the worst-case scenario */
|
/* Adjust for potential quotes. Also assume the worst-case scenario that
|
||||||
/* that every character needs escaping, so we need twice as much space. */
|
* every character needs escaping, so we need twice as much space. */
|
||||||
dst_len = dst_len * 2 + arg_count * 2;
|
dst_len = dst_len * 2 + arg_count * 2;
|
||||||
|
|
||||||
/* Allocate buffer for the final command line. */
|
/* Allocate buffer for the final command line. */
|
||||||
@@ -739,7 +739,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ptr_copy = NULL;
|
*ptr_copy = NULL;
|
||||||
assert(env_len == ptr - dst_copy);
|
assert(env_len == (size_t) (ptr - dst_copy));
|
||||||
|
|
||||||
/* sort our (UTF-16) copy */
|
/* sort our (UTF-16) copy */
|
||||||
qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
|
qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
|
||||||
@@ -799,7 +799,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
|||||||
var_size = GetEnvironmentVariableW(required_vars[i].wide,
|
var_size = GetEnvironmentVariableW(required_vars[i].wide,
|
||||||
ptr,
|
ptr,
|
||||||
(int) (env_len - (ptr - dst)));
|
(int) (env_len - (ptr - dst)));
|
||||||
if (var_size != len-1) { /* race condition? */
|
if (var_size != (DWORD) (len - 1)) { /* TODO: handle race condition? */
|
||||||
uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
|
uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -815,7 +815,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Terminate with an extra NULL. */
|
/* Terminate with an extra NULL. */
|
||||||
assert(env_len == (ptr - dst));
|
assert(env_len == (size_t) (ptr - dst));
|
||||||
*ptr = L'\0';
|
*ptr = L'\0';
|
||||||
|
|
||||||
uv__free(dst_copy);
|
uv__free(dst_copy);
|
||||||
@@ -831,8 +831,13 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
|
|||||||
*/
|
*/
|
||||||
static WCHAR* find_path(WCHAR *env) {
|
static WCHAR* find_path(WCHAR *env) {
|
||||||
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
|
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
|
||||||
if (wcsncmp(env, L"PATH=", 5) == 0)
|
if ((env[0] == L'P' || env[0] == L'p') &&
|
||||||
|
(env[1] == L'A' || env[1] == L'a') &&
|
||||||
|
(env[2] == L'T' || env[2] == L't') &&
|
||||||
|
(env[3] == L'H' || env[3] == L'h') &&
|
||||||
|
(env[4] == L'=')) {
|
||||||
return &env[5];
|
return &env[5];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -865,9 +870,9 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
|
|||||||
assert(handle->exit_cb_pending);
|
assert(handle->exit_cb_pending);
|
||||||
handle->exit_cb_pending = 0;
|
handle->exit_cb_pending = 0;
|
||||||
|
|
||||||
/* If we're closing, don't call the exit callback. Just schedule a close */
|
/* If we're closing, don't call the exit callback. Just schedule a close
|
||||||
/* callback now. */
|
* callback now. */
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -878,14 +883,14 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
|
|||||||
handle->wait_handle = INVALID_HANDLE_VALUE;
|
handle->wait_handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the handle to inactive: no callbacks will be made after the exit */
|
/* Set the handle to inactive: no callbacks will be made after the exit
|
||||||
/* callback.*/
|
* callback. */
|
||||||
uv__handle_stop(handle);
|
uv__handle_stop(handle);
|
||||||
|
|
||||||
if (GetExitCodeProcess(handle->process_handle, &status)) {
|
if (GetExitCodeProcess(handle->process_handle, &status)) {
|
||||||
exit_code = status;
|
exit_code = status;
|
||||||
} else {
|
} else {
|
||||||
/* Unable to to obtain the exit code. This should never happen. */
|
/* Unable to obtain the exit code. This should never happen. */
|
||||||
exit_code = uv_translate_sys_error(GetLastError());
|
exit_code = uv_translate_sys_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,8 +905,8 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
|
|||||||
uv__handle_closing(handle);
|
uv__handle_closing(handle);
|
||||||
|
|
||||||
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
|
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
|
||||||
/* This blocks until either the wait was cancelled, or the callback has */
|
/* This blocks until either the wait was cancelled, or the callback has
|
||||||
/* completed. */
|
* completed. */
|
||||||
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
|
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
/* This should never happen, and if it happens, we can't recover... */
|
/* This should never happen, and if it happens, we can't recover... */
|
||||||
@@ -919,7 +924,7 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
|
|||||||
|
|
||||||
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
|
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
|
||||||
assert(!handle->exit_cb_pending);
|
assert(!handle->exit_cb_pending);
|
||||||
assert(handle->flags & UV__HANDLE_CLOSING);
|
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
|
|
||||||
/* Clean-up the process handle. */
|
/* Clean-up the process handle. */
|
||||||
@@ -965,6 +970,8 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
UV_PROCESS_SETGID |
|
UV_PROCESS_SETGID |
|
||||||
UV_PROCESS_SETUID |
|
UV_PROCESS_SETUID |
|
||||||
UV_PROCESS_WINDOWS_HIDE |
|
UV_PROCESS_WINDOWS_HIDE |
|
||||||
|
UV_PROCESS_WINDOWS_HIDE_CONSOLE |
|
||||||
|
UV_PROCESS_WINDOWS_HIDE_GUI |
|
||||||
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
|
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
|
||||||
|
|
||||||
err = uv_utf8_to_utf16_alloc(options->file, &application);
|
err = uv_utf8_to_utf16_alloc(options->file, &application);
|
||||||
@@ -1066,7 +1073,8 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
|
|
||||||
process_flags = CREATE_UNICODE_ENVIRONMENT;
|
process_flags = CREATE_UNICODE_ENVIRONMENT;
|
||||||
|
|
||||||
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
|
if ((options->flags & UV_PROCESS_WINDOWS_HIDE_CONSOLE) ||
|
||||||
|
(options->flags & UV_PROCESS_WINDOWS_HIDE)) {
|
||||||
/* Avoid creating console window if stdio is not inherited. */
|
/* Avoid creating console window if stdio is not inherited. */
|
||||||
for (i = 0; i < options->stdio_count; i++) {
|
for (i = 0; i < options->stdio_count; i++) {
|
||||||
if (options->stdio[i].flags & UV_INHERIT_FD)
|
if (options->stdio[i].flags & UV_INHERIT_FD)
|
||||||
@@ -1074,7 +1082,9 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
if (i == options->stdio_count - 1)
|
if (i == options->stdio_count - 1)
|
||||||
process_flags |= CREATE_NO_WINDOW;
|
process_flags |= CREATE_NO_WINDOW;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ((options->flags & UV_PROCESS_WINDOWS_HIDE_GUI) ||
|
||||||
|
(options->flags & UV_PROCESS_WINDOWS_HIDE)) {
|
||||||
/* Use SW_HIDE to avoid any potential process window. */
|
/* Use SW_HIDE to avoid any potential process window. */
|
||||||
startup.wShowWindow = SW_HIDE;
|
startup.wShowWindow = SW_HIDE;
|
||||||
} else {
|
} else {
|
||||||
@@ -1160,14 +1170,13 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spawn succeeded */
|
/* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
|
||||||
/* Beyond this point, failure is reported asynchronously. */
|
|
||||||
|
|
||||||
process->process_handle = info.hProcess;
|
process->process_handle = info.hProcess;
|
||||||
process->pid = info.dwProcessId;
|
process->pid = info.dwProcessId;
|
||||||
|
|
||||||
/* If the process isn't spawned as detached, assign to the global job */
|
/* If the process isn't spawned as detached, assign to the global job object
|
||||||
/* object so windows will kill it when the parent process dies. */
|
* so windows will kill it when the parent process dies. */
|
||||||
if (!(options->flags & UV_PROCESS_DETACHED)) {
|
if (!(options->flags & UV_PROCESS_DETACHED)) {
|
||||||
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
|
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
|
||||||
|
|
||||||
@@ -1194,7 +1203,8 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
if (fdopt->flags & UV_CREATE_PIPE &&
|
if (fdopt->flags & UV_CREATE_PIPE &&
|
||||||
fdopt->data.stream->type == UV_NAMED_PIPE &&
|
fdopt->data.stream->type == UV_NAMED_PIPE &&
|
||||||
((uv_pipe_t*) fdopt->data.stream)->ipc) {
|
((uv_pipe_t*) fdopt->data.stream)->ipc) {
|
||||||
((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId;
|
((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =
|
||||||
|
info.dwProcessId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1210,8 +1220,8 @@ int uv_spawn(uv_loop_t* loop,
|
|||||||
|
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
/* Make the handle active. It will remain active until the exit callback */
|
/* Make the handle active. It will remain active until the exit callback is
|
||||||
/* is made or the handle is closed, whichever happens first. */
|
* made or the handle is closed, whichever happens first. */
|
||||||
uv__handle_start(process);
|
uv__handle_start(process);
|
||||||
|
|
||||||
/* Cleanup, whether we succeeded or failed. */
|
/* Cleanup, whether we succeeded or failed. */
|
||||||
@@ -1242,16 +1252,16 @@ static int uv__kill(HANDLE process_handle, int signum) {
|
|||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
case SIGKILL:
|
case SIGKILL:
|
||||||
case SIGINT: {
|
case SIGINT: {
|
||||||
/* Unconditionally terminate the process. On Windows, killed processes */
|
/* Unconditionally terminate the process. On Windows, killed processes
|
||||||
/* normally return 1. */
|
* normally return 1. */
|
||||||
DWORD status;
|
DWORD status;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (TerminateProcess(process_handle, 1))
|
if (TerminateProcess(process_handle, 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If the process already exited before TerminateProcess was called, */
|
/* If the process already exited before TerminateProcess was called,.
|
||||||
/* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
|
* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
if (err == ERROR_ACCESS_DENIED &&
|
if (err == ERROR_ACCESS_DENIED &&
|
||||||
GetExitCodeProcess(process_handle, &status) &&
|
GetExitCodeProcess(process_handle, &status) &&
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to
|
|
||||||
* deal in the Software without restriction, including without limitation the
|
|
||||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
* sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
* IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "uv.h"
|
|
||||||
#include "internal.h"
|
|
||||||
@@ -47,13 +47,13 @@ void uv_signals_init(void) {
|
|||||||
|
|
||||||
|
|
||||||
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
|
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
|
||||||
/* Compare signums first so all watchers with the same signnum end up */
|
/* Compare signums first so all watchers with the same signnum end up
|
||||||
/* adjacent. */
|
* adjacent. */
|
||||||
if (w1->signum < w2->signum) return -1;
|
if (w1->signum < w2->signum) return -1;
|
||||||
if (w1->signum > w2->signum) return 1;
|
if (w1->signum > w2->signum) return 1;
|
||||||
|
|
||||||
/* Sort by loop pointer, so we can easily look up the first item after */
|
/* Sort by loop pointer, so we can easily look up the first item after
|
||||||
/* { .signum = x, .loop = NULL } */
|
* { .signum = x, .loop = NULL }. */
|
||||||
if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
|
if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
|
||||||
if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
|
if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ int uv__signal_dispatch(int signum) {
|
|||||||
unsigned long previous = InterlockedExchange(
|
unsigned long previous = InterlockedExchange(
|
||||||
(volatile LONG*) &handle->pending_signum, signum);
|
(volatile LONG*) &handle->pending_signum, signum);
|
||||||
|
|
||||||
if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED)
|
if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!previous) {
|
if (!previous) {
|
||||||
@@ -98,8 +98,8 @@ int uv__signal_dispatch(int signum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatched = 1;
|
dispatched = 1;
|
||||||
if (handle->flags & UV__SIGNAL_ONE_SHOT)
|
if (handle->flags & UV_SIGNAL_ONE_SHOT)
|
||||||
handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED;
|
handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&uv__signal_lock);
|
LeaveCriticalSection(&uv__signal_lock);
|
||||||
@@ -118,10 +118,10 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
|
|||||||
|
|
||||||
case CTRL_CLOSE_EVENT:
|
case CTRL_CLOSE_EVENT:
|
||||||
if (uv__signal_dispatch(SIGHUP)) {
|
if (uv__signal_dispatch(SIGHUP)) {
|
||||||
/* Windows will terminate the process after the control handler */
|
/* Windows will terminate the process after the control handler
|
||||||
/* returns. After that it will just terminate our process. Therefore */
|
* returns. After that it will just terminate our process. Therefore
|
||||||
/* block the signal handler so the main loop has some time to pick */
|
* block the signal handler so the main loop has some time to pick up
|
||||||
/* up the signal and do something for a few seconds. */
|
* the signal and do something for a few seconds. */
|
||||||
Sleep(INFINITE);
|
Sleep(INFINITE);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -129,8 +129,8 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
|
|||||||
|
|
||||||
case CTRL_LOGOFF_EVENT:
|
case CTRL_LOGOFF_EVENT:
|
||||||
case CTRL_SHUTDOWN_EVENT:
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
/* These signals are only sent to services. Services have their own */
|
/* These signals are only sent to services. Services have their own
|
||||||
/* notification mechanism, so there's no point in handling these. */
|
* notification mechanism, so there's no point in handling these. */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* We don't handle these. */
|
/* We don't handle these. */
|
||||||
@@ -190,13 +190,13 @@ int uv__signal_start(uv_signal_t* handle,
|
|||||||
int signum,
|
int signum,
|
||||||
int oneshot) {
|
int oneshot) {
|
||||||
/* Test for invalid signal values. */
|
/* Test for invalid signal values. */
|
||||||
if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
|
if (signum <= 0 || signum >= NSIG)
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
/* Short circuit: if the signal watcher is already watching {signum} don't */
|
/* Short circuit: if the signal watcher is already watching {signum} don't go
|
||||||
/* go through the process of deregistering and registering the handler. */
|
* through the process of deregistering and registering the handler.
|
||||||
/* Additionally, this avoids pending signals getting lost in the (small) */
|
* Additionally, this avoids pending signals getting lost in the (small) time
|
||||||
/* time frame that handle->signum == 0. */
|
* frame that handle->signum == 0. */
|
||||||
if (signum == handle->signum) {
|
if (signum == handle->signum) {
|
||||||
handle->signal_cb = signal_cb;
|
handle->signal_cb = signal_cb;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -213,7 +213,7 @@ int uv__signal_start(uv_signal_t* handle,
|
|||||||
|
|
||||||
handle->signum = signum;
|
handle->signum = signum;
|
||||||
if (oneshot)
|
if (oneshot)
|
||||||
handle->flags |= UV__SIGNAL_ONE_SHOT;
|
handle->flags |= UV_SIGNAL_ONE_SHOT;
|
||||||
|
|
||||||
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
|
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
|
||||||
|
|
||||||
@@ -237,16 +237,16 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
|
|||||||
(volatile LONG*) &handle->pending_signum, 0);
|
(volatile LONG*) &handle->pending_signum, 0);
|
||||||
assert(dispatched_signum != 0);
|
assert(dispatched_signum != 0);
|
||||||
|
|
||||||
/* Check if the pending signal equals the signum that we are watching for. */
|
/* Check if the pending signal equals the signum that we are watching for.
|
||||||
/* These can get out of sync when the handler is stopped and restarted */
|
* These can get out of sync when the handler is stopped and restarted while
|
||||||
/* while the signal_req is pending. */
|
* the signal_req is pending. */
|
||||||
if (dispatched_signum == handle->signum)
|
if (dispatched_signum == handle->signum)
|
||||||
handle->signal_cb(handle, dispatched_signum);
|
handle->signal_cb(handle, dispatched_signum);
|
||||||
|
|
||||||
if (handle->flags & UV__SIGNAL_ONE_SHOT)
|
if (handle->flags & UV_SIGNAL_ONE_SHOT)
|
||||||
uv_signal_stop(handle);
|
uv_signal_stop(handle);
|
||||||
|
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
/* When it is closing, it must be stopped at this point. */
|
/* When it is closing, it must be stopped at this point. */
|
||||||
assert(handle->signum == 0);
|
assert(handle->signum == 0);
|
||||||
uv_want_endgame(loop, (uv_handle_t*) handle);
|
uv_want_endgame(loop, (uv_handle_t*) handle);
|
||||||
@@ -265,7 +265,7 @@ void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
|
void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
|
||||||
assert(handle->flags & UV__HANDLE_CLOSING);
|
assert(handle->flags & UV_HANDLE_CLOSING);
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
|
|
||||||
assert(handle->signum == 0);
|
assert(handle->signum == 0);
|
||||||
|
|||||||
@@ -105,12 +105,10 @@ int uv_read_stop(uv_stream_t* handle) {
|
|||||||
err = 0;
|
err = 0;
|
||||||
if (handle->type == UV_TTY) {
|
if (handle->type == UV_TTY) {
|
||||||
err = uv_tty_read_stop((uv_tty_t*) handle);
|
err = uv_tty_read_stop((uv_tty_t*) handle);
|
||||||
|
} else if (handle->type == UV_NAMED_PIPE) {
|
||||||
|
uv__pipe_read_stop((uv_pipe_t*) handle);
|
||||||
} else {
|
} else {
|
||||||
if (handle->type == UV_NAMED_PIPE) {
|
handle->flags &= ~UV_HANDLE_READING;
|
||||||
uv__pipe_stop_read((uv_pipe_t*) handle);
|
|
||||||
} else {
|
|
||||||
handle->flags &= ~UV_HANDLE_READING;
|
|
||||||
}
|
|
||||||
DECREASE_ACTIVE_COUNT(handle->loop, handle);
|
DECREASE_ACTIVE_COUNT(handle->loop, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +134,8 @@ int uv_write(uv_write_t* req,
|
|||||||
err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
|
err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
|
||||||
break;
|
break;
|
||||||
case UV_NAMED_PIPE:
|
case UV_NAMED_PIPE:
|
||||||
err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb);
|
err = uv__pipe_write(
|
||||||
|
loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);
|
||||||
break;
|
break;
|
||||||
case UV_TTY:
|
case UV_TTY:
|
||||||
err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
|
err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
|
||||||
@@ -158,25 +157,18 @@ int uv_write2(uv_write_t* req,
|
|||||||
uv_loop_t* loop = handle->loop;
|
uv_loop_t* loop = handle->loop;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(handle->flags & UV_HANDLE_WRITABLE)) {
|
if (send_handle == NULL) {
|
||||||
|
return uv_write(req, handle, bufs, nbufs, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) {
|
||||||
|
return UV_EINVAL;
|
||||||
|
} else if (!(handle->flags & UV_HANDLE_WRITABLE)) {
|
||||||
return UV_EPIPE;
|
return UV_EPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ERROR_INVALID_PARAMETER;
|
err = uv__pipe_write(
|
||||||
switch (handle->type) {
|
loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb);
|
||||||
case UV_NAMED_PIPE:
|
|
||||||
err = uv_pipe_write2(loop,
|
|
||||||
req,
|
|
||||||
(uv_pipe_t*) handle,
|
|
||||||
bufs,
|
|
||||||
nbufs,
|
|
||||||
send_handle,
|
|
||||||
cb);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uv_translate_sys_error(err);
|
return uv_translate_sys_error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +176,7 @@ int uv_write2(uv_write_t* req,
|
|||||||
int uv_try_write(uv_stream_t* stream,
|
int uv_try_write(uv_stream_t* stream,
|
||||||
const uv_buf_t bufs[],
|
const uv_buf_t bufs[],
|
||||||
unsigned int nbufs) {
|
unsigned int nbufs) {
|
||||||
if (stream->flags & UV__HANDLE_CLOSING)
|
if (stream->flags & UV_HANDLE_CLOSING)
|
||||||
return UV_EBADF;
|
return UV_EBADF;
|
||||||
if (!(stream->flags & UV_HANDLE_WRITABLE))
|
if (!(stream->flags & UV_HANDLE_WRITABLE))
|
||||||
return UV_EPIPE;
|
return UV_EPIPE;
|
||||||
|
|||||||
+106
-107
@@ -99,8 +99,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
|
|||||||
if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
|
if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
|
|
||||||
/* Associate it with the I/O completion port. */
|
/* Associate it with the I/O completion port. Use uv_handle_t pointer as
|
||||||
/* Use uv_handle_t pointer as completion key. */
|
* completion key. */
|
||||||
if (CreateIoCompletionPort((HANDLE)socket,
|
if (CreateIoCompletionPort((HANDLE)socket,
|
||||||
loop->iocp,
|
loop->iocp,
|
||||||
(ULONG_PTR)socket,
|
(ULONG_PTR)socket,
|
||||||
@@ -118,15 +118,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop,
|
|||||||
non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
|
non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSetFileCompletionNotificationModes &&
|
if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
|
||||||
!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
|
UCHAR sfcnm_flags =
|
||||||
if (pSetFileCompletionNotificationModes((HANDLE) socket,
|
FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
|
||||||
FILE_SKIP_SET_EVENT_ON_HANDLE |
|
if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags))
|
||||||
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
|
|
||||||
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
|
||||||
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
|
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_TCP_NODELAY) {
|
if (handle->flags & UV_HANDLE_TCP_NODELAY) {
|
||||||
@@ -220,7 +217,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||||||
UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
|
UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
err = ERROR_OPERATION_ABORTED;
|
err = ERROR_OPERATION_ABORTED;
|
||||||
} else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
|
} else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
|
||||||
err = WSAGetLastError();
|
err = WSAGetLastError();
|
||||||
@@ -236,7 +233,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->flags & UV__HANDLE_CLOSING &&
|
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||||
handle->reqs_pending == 0) {
|
handle->reqs_pending == 0) {
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
|
|
||||||
@@ -326,9 +323,9 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
|
|||||||
|
|
||||||
on = (flags & UV_TCP_IPV6ONLY) != 0;
|
on = (flags & UV_TCP_IPV6ONLY) != 0;
|
||||||
|
|
||||||
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
|
/* TODO: how to handle errors? This may fail if there is no ipv4 stack
|
||||||
/* available, or when run on XP/2003 which have no support for dualstack */
|
* available, or when run on XP/2003 which have no support for dualstack
|
||||||
/* sockets. For now we're silently ignoring the error. */
|
* sockets. For now we're silently ignoring the error. */
|
||||||
setsockopt(handle->socket,
|
setsockopt(handle->socket,
|
||||||
IPPROTO_IPV6,
|
IPPROTO_IPV6,
|
||||||
IPV6_V6ONLY,
|
IPV6_V6ONLY,
|
||||||
@@ -626,9 +623,9 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
|||||||
uv_tcp_queue_accept(handle, req);
|
uv_tcp_queue_accept(handle, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize other unused requests too, because uv_tcp_endgame */
|
/* Initialize other unused requests too, because uv_tcp_endgame doesn't
|
||||||
/* doesn't know how how many requests were initialized, so it will */
|
* know how many requests were initialized, so it will try to clean up
|
||||||
/* try to clean up {uv_simultaneous_server_accepts} requests. */
|
* {uv_simultaneous_server_accepts} requests. */
|
||||||
for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
|
for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
|
||||||
req = &handle->tcp.serv.accept_reqs[i];
|
req = &handle->tcp.serv.accept_reqs[i];
|
||||||
UV_REQ_INIT(req, UV_ACCEPT);
|
UV_REQ_INIT(req, UV_ACCEPT);
|
||||||
@@ -683,7 +680,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
|
|||||||
req->next_pending = NULL;
|
req->next_pending = NULL;
|
||||||
req->accept_socket = INVALID_SOCKET;
|
req->accept_socket = INVALID_SOCKET;
|
||||||
|
|
||||||
if (!(server->flags & UV__HANDLE_CLOSING)) {
|
if (!(server->flags & UV_HANDLE_CLOSING)) {
|
||||||
/* Check if we're in a middle of changing the number of pending accepts. */
|
/* Check if we're in a middle of changing the number of pending accepts. */
|
||||||
if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
|
if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
|
||||||
uv_tcp_queue_accept(server, req);
|
uv_tcp_queue_accept(server, req);
|
||||||
@@ -721,8 +718,8 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
|
|||||||
handle->alloc_cb = alloc_cb;
|
handle->alloc_cb = alloc_cb;
|
||||||
INCREASE_ACTIVE_COUNT(loop, handle);
|
INCREASE_ACTIVE_COUNT(loop, handle);
|
||||||
|
|
||||||
/* If reading was stopped and then started again, there could still be a */
|
/* If reading was stopped and then started again, there could still be a read
|
||||||
/* read request pending. */
|
* request pending. */
|
||||||
if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
|
if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
|
||||||
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
|
if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
|
||||||
!handle->read_req.event_handle) {
|
!handle->read_req.event_handle) {
|
||||||
@@ -948,6 +945,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
uv_req_t* req) {
|
uv_req_t* req) {
|
||||||
DWORD bytes, flags, err;
|
DWORD bytes, flags, err;
|
||||||
uv_buf_t buf;
|
uv_buf_t buf;
|
||||||
|
int count;
|
||||||
|
|
||||||
assert(handle->type == UV_TCP);
|
assert(handle->type == UV_TCP);
|
||||||
|
|
||||||
@@ -965,8 +963,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
err = GET_REQ_SOCK_ERROR(req);
|
err = GET_REQ_SOCK_ERROR(req);
|
||||||
|
|
||||||
if (err == WSAECONNABORTED) {
|
if (err == WSAECONNABORTED) {
|
||||||
/*
|
/* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
|
||||||
* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
|
|
||||||
*/
|
*/
|
||||||
err = WSAECONNRESET;
|
err = WSAECONNRESET;
|
||||||
}
|
}
|
||||||
@@ -1003,7 +1000,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do nonblocking reads until the buffer is empty */
|
/* Do nonblocking reads until the buffer is empty */
|
||||||
while (handle->flags & UV_HANDLE_READING) {
|
count = 32;
|
||||||
|
while ((handle->flags & UV_HANDLE_READING) && (count-- > 0)) {
|
||||||
buf = uv_buf_init(NULL, 0);
|
buf = uv_buf_init(NULL, 0);
|
||||||
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
|
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
|
||||||
if (buf.base == NULL || buf.len == 0) {
|
if (buf.base == NULL || buf.len == 0) {
|
||||||
@@ -1046,8 +1044,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
DECREASE_ACTIVE_COUNT(loop, handle);
|
DECREASE_ACTIVE_COUNT(loop, handle);
|
||||||
|
|
||||||
if (err == WSAECONNABORTED) {
|
if (err == WSAECONNABORTED) {
|
||||||
/* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */
|
/* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with
|
||||||
/* Unix. */
|
* Unix. */
|
||||||
err = WSAECONNRESET;
|
err = WSAECONNRESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1119,10 +1117,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
|
|
||||||
assert(handle->type == UV_TCP);
|
assert(handle->type == UV_TCP);
|
||||||
|
|
||||||
/* If handle->accepted_socket is not a valid socket, then */
|
/* If handle->accepted_socket is not a valid socket, then uv_queue_accept
|
||||||
/* uv_queue_accept must have failed. This is a serious error. We stop */
|
* must have failed. This is a serious error. We stop accepting connections
|
||||||
/* accepting connections and report this error to the connection */
|
* and report this error to the connection callback. */
|
||||||
/* callback. */
|
|
||||||
if (req->accept_socket == INVALID_SOCKET) {
|
if (req->accept_socket == INVALID_SOCKET) {
|
||||||
if (handle->flags & UV_HANDLE_LISTENING) {
|
if (handle->flags & UV_HANDLE_LISTENING) {
|
||||||
handle->flags &= ~UV_HANDLE_LISTENING;
|
handle->flags &= ~UV_HANDLE_LISTENING;
|
||||||
@@ -1147,9 +1144,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
|
handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Error related to accepted socket is ignored because the server */
|
/* Error related to accepted socket is ignored because the server socket
|
||||||
/* socket may still be healthy. If the server socket is broken */
|
* may still be healthy. If the server socket is broken uv_queue_accept
|
||||||
/* uv_queue_accept will detect it. */
|
* will detect it. */
|
||||||
closesocket(req->accept_socket);
|
closesocket(req->accept_socket);
|
||||||
req->accept_socket = INVALID_SOCKET;
|
req->accept_socket = INVALID_SOCKET;
|
||||||
if (handle->flags & UV_HANDLE_LISTENING) {
|
if (handle->flags & UV_HANDLE_LISTENING) {
|
||||||
@@ -1171,7 +1168,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
if (REQ_SUCCESS(req)) {
|
if (REQ_SUCCESS(req)) {
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
/* use UV_ECANCELED for consistency with Unix */
|
/* use UV_ECANCELED for consistency with Unix */
|
||||||
err = ERROR_OPERATION_ABORTED;
|
err = ERROR_OPERATION_ABORTED;
|
||||||
} else if (setsockopt(handle->socket,
|
} else if (setsockopt(handle->socket,
|
||||||
@@ -1194,40 +1191,76 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
|
int uv__tcp_xfer_export(uv_tcp_t* handle,
|
||||||
int tcp_connection) {
|
int target_pid,
|
||||||
|
uv__ipc_socket_xfer_type_t* xfer_type,
|
||||||
|
uv__ipc_socket_xfer_info_t* xfer_info) {
|
||||||
|
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||||
|
*xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION;
|
||||||
|
} else {
|
||||||
|
*xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER;
|
||||||
|
/* We're about to share the socket with another process. Because this is a
|
||||||
|
* listening socket, we assume that the other process will be accepting
|
||||||
|
* connections on it. Thus, before sharing the socket with another process,
|
||||||
|
* we call listen here in the parent process. */
|
||||||
|
if (!(handle->flags & UV_HANDLE_LISTENING)) {
|
||||||
|
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||||
|
return ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
if (handle->delayed_error == 0 &&
|
||||||
|
listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
|
||||||
|
handle->delayed_error = WSAGetLastError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info))
|
||||||
|
return WSAGetLastError();
|
||||||
|
xfer_info->delayed_error = handle->delayed_error;
|
||||||
|
|
||||||
|
/* Mark the local copy of the handle as 'shared' so we behave in a way that's
|
||||||
|
* friendly to the process(es) that we share the socket with. */
|
||||||
|
handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv__tcp_xfer_import(uv_tcp_t* tcp,
|
||||||
|
uv__ipc_socket_xfer_type_t xfer_type,
|
||||||
|
uv__ipc_socket_xfer_info_t* xfer_info) {
|
||||||
int err;
|
int err;
|
||||||
SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO,
|
SOCKET socket;
|
||||||
FROM_PROTOCOL_INFO,
|
|
||||||
FROM_PROTOCOL_INFO,
|
assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER ||
|
||||||
&socket_info_ex->socket_info,
|
xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION);
|
||||||
0,
|
|
||||||
WSA_FLAG_OVERLAPPED);
|
socket = WSASocketW(FROM_PROTOCOL_INFO,
|
||||||
|
FROM_PROTOCOL_INFO,
|
||||||
|
FROM_PROTOCOL_INFO,
|
||||||
|
&xfer_info->socket_info,
|
||||||
|
0,
|
||||||
|
WSA_FLAG_OVERLAPPED);
|
||||||
|
|
||||||
if (socket == INVALID_SOCKET) {
|
if (socket == INVALID_SOCKET) {
|
||||||
return WSAGetLastError();
|
return WSAGetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
err = uv_tcp_set_socket(tcp->loop,
|
err = uv_tcp_set_socket(
|
||||||
tcp,
|
tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);
|
||||||
socket,
|
|
||||||
socket_info_ex->socket_info.iAddressFamily,
|
|
||||||
1);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
closesocket(socket);
|
closesocket(socket);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcp_connection) {
|
tcp->delayed_error = xfer_info->delayed_error;
|
||||||
|
tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
|
||||||
|
|
||||||
|
if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {
|
||||||
uv_connection_init((uv_stream_t*)tcp);
|
uv_connection_init((uv_stream_t*)tcp);
|
||||||
tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
|
tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp->flags |= UV_HANDLE_BOUND;
|
|
||||||
tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
|
|
||||||
|
|
||||||
tcp->delayed_error = socket_info_ex->delayed_error;
|
|
||||||
|
|
||||||
tcp->loop->active_tcp_streams++;
|
tcp->loop->active_tcp_streams++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1273,39 +1306,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
|
|
||||||
LPWSAPROTOCOL_INFOW protocol_info) {
|
|
||||||
if (!(handle->flags & UV_HANDLE_CONNECTION)) {
|
|
||||||
/*
|
|
||||||
* We're about to share the socket with another process. Because
|
|
||||||
* this is a listening socket, we assume that the other process will
|
|
||||||
* be accepting connections on it. So, before sharing the socket
|
|
||||||
* with another process, we call listen here in the parent process.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!(handle->flags & UV_HANDLE_LISTENING)) {
|
|
||||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
|
||||||
return ERROR_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(handle->delayed_error)) {
|
|
||||||
if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
|
|
||||||
handle->delayed_error = WSAGetLastError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) {
|
|
||||||
return WSAGetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
@@ -1346,8 +1346,8 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
|
|||||||
non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
|
non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
|
||||||
uv_tcp_non_ifs_lsp_ipv4;
|
uv_tcp_non_ifs_lsp_ipv4;
|
||||||
|
|
||||||
/* If there are non-ifs LSPs then try to obtain a base handle for the */
|
/* If there are non-ifs LSPs then try to obtain a base handle for the socket.
|
||||||
/* socket. This will always fail on Windows XP/3k. */
|
* This will always fail on Windows XP/3k. */
|
||||||
if (non_ifs_lsp) {
|
if (non_ifs_lsp) {
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
if (WSAIoctl(socket,
|
if (WSAIoctl(socket,
|
||||||
@@ -1379,38 +1379,37 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
|
|||||||
int close_socket = 1;
|
int close_socket = 1;
|
||||||
|
|
||||||
if (tcp->flags & UV_HANDLE_READ_PENDING) {
|
if (tcp->flags & UV_HANDLE_READ_PENDING) {
|
||||||
/* In order for winsock to do a graceful close there must not be any */
|
/* In order for winsock to do a graceful close there must not be any any
|
||||||
/* any pending reads, or the socket must be shut down for writing */
|
* pending reads, or the socket must be shut down for writing */
|
||||||
if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
|
if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
|
||||||
/* Just do shutdown on non-shared sockets, which ensures graceful close. */
|
/* Just do shutdown on non-shared sockets, which ensures graceful close. */
|
||||||
shutdown(tcp->socket, SD_SEND);
|
shutdown(tcp->socket, SD_SEND);
|
||||||
|
|
||||||
} else if (uv_tcp_try_cancel_io(tcp) == 0) {
|
} else if (uv_tcp_try_cancel_io(tcp) == 0) {
|
||||||
/* In case of a shared socket, we try to cancel all outstanding I/O, */
|
/* In case of a shared socket, we try to cancel all outstanding I/O,. If
|
||||||
/* If that works, don't close the socket yet - wait for the read req to */
|
* that works, don't close the socket yet - wait for the read req to
|
||||||
/* return and close the socket in uv_tcp_endgame. */
|
* return and close the socket in uv_tcp_endgame. */
|
||||||
close_socket = 0;
|
close_socket = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* When cancelling isn't possible - which could happen when an LSP is */
|
/* When cancelling isn't possible - which could happen when an LSP is
|
||||||
/* present on an old Windows version, we will have to close the socket */
|
* present on an old Windows version, we will have to close the socket
|
||||||
/* with a read pending. That is not nice because trailing sent bytes */
|
* with a read pending. That is not nice because trailing sent bytes may
|
||||||
/* may not make it to the other side. */
|
* not make it to the other side. */
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
|
} else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
|
||||||
tcp->tcp.serv.accept_reqs != NULL) {
|
tcp->tcp.serv.accept_reqs != NULL) {
|
||||||
/* Under normal circumstances closesocket() will ensure that all pending */
|
/* Under normal circumstances closesocket() will ensure that all pending
|
||||||
/* accept reqs are canceled. However, when the socket is shared the */
|
* accept reqs are canceled. However, when the socket is shared the
|
||||||
/* presence of another reference to the socket in another process will */
|
* presence of another reference to the socket in another process will keep
|
||||||
/* keep the accept reqs going, so we have to ensure that these are */
|
* the accept reqs going, so we have to ensure that these are canceled. */
|
||||||
/* canceled. */
|
|
||||||
if (uv_tcp_try_cancel_io(tcp) != 0) {
|
if (uv_tcp_try_cancel_io(tcp) != 0) {
|
||||||
/* When cancellation is not possible, there is another option: we can */
|
/* When cancellation is not possible, there is another option: we can
|
||||||
/* close the incoming sockets, which will also cancel the accept */
|
* close the incoming sockets, which will also cancel the accept
|
||||||
/* operations. However this is not cool because we might inadvertently */
|
* operations. However this is not cool because we might inadvertently
|
||||||
/* close a socket that just accepted a new connection, which will */
|
* close a socket that just accepted a new connection, which will cause
|
||||||
/* cause the connection to be aborted. */
|
* the connection to be aborted. */
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
||||||
uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
|
uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
|
||||||
|
|||||||
@@ -23,29 +23,15 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(__MINGW64_VERSION_MAJOR)
|
||||||
|
/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may
|
||||||
|
* require this header in some versions of mingw64. */
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
|
|
||||||
|
|
||||||
static int uv_cond_fallback_init(uv_cond_t* cond);
|
|
||||||
static void uv_cond_fallback_destroy(uv_cond_t* cond);
|
|
||||||
static void uv_cond_fallback_signal(uv_cond_t* cond);
|
|
||||||
static void uv_cond_fallback_broadcast(uv_cond_t* cond);
|
|
||||||
static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
|
|
||||||
static int uv_cond_fallback_timedwait(uv_cond_t* cond,
|
|
||||||
uv_mutex_t* mutex, uint64_t timeout);
|
|
||||||
|
|
||||||
static int uv_cond_condvar_init(uv_cond_t* cond);
|
|
||||||
static void uv_cond_condvar_destroy(uv_cond_t* cond);
|
|
||||||
static void uv_cond_condvar_signal(uv_cond_t* cond);
|
|
||||||
static void uv_cond_condvar_broadcast(uv_cond_t* cond);
|
|
||||||
static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex);
|
|
||||||
static int uv_cond_condvar_timedwait(uv_cond_t* cond,
|
|
||||||
uv_mutex_t* mutex, uint64_t timeout);
|
|
||||||
|
|
||||||
|
|
||||||
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
|
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
|
||||||
DWORD result;
|
DWORD result;
|
||||||
HANDLE existing_event, created_event;
|
HANDLE existing_event, created_event;
|
||||||
@@ -69,8 +55,8 @@ static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
|
|||||||
guard->ran = 1;
|
guard->ran = 1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* We lost the race. Destroy the event we created and wait for the */
|
/* We lost the race. Destroy the event we created and wait for the existing
|
||||||
/* existing one to become signaled. */
|
* one to become signaled. */
|
||||||
CloseHandle(created_event);
|
CloseHandle(created_event);
|
||||||
result = WaitForSingleObject(existing_event, INFINITE);
|
result = WaitForSingleObject(existing_event, INFINITE);
|
||||||
assert(result == WAIT_OBJECT_0);
|
assert(result == WAIT_OBJECT_0);
|
||||||
@@ -138,7 +124,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
|||||||
ctx->arg = arg;
|
ctx->arg = arg;
|
||||||
|
|
||||||
/* Create the thread in suspended state so we have a chance to pass
|
/* Create the thread in suspended state so we have a chance to pass
|
||||||
* its own creation handle to it */
|
* its own creation handle to it */
|
||||||
thread = (HANDLE) _beginthreadex(NULL,
|
thread = (HANDLE) _beginthreadex(NULL,
|
||||||
0,
|
0,
|
||||||
uv__thread_start,
|
uv__thread_start,
|
||||||
@@ -377,220 +363,35 @@ int uv_sem_trywait(uv_sem_t* sem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This condition variable implementation is based on the SetEvent solution
|
|
||||||
* (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
|
|
||||||
* We could not use the SignalObjectAndWait solution (section 3.4) because
|
|
||||||
* it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
|
|
||||||
* uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int uv_cond_fallback_init(uv_cond_t* cond) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
/* Initialize the count to 0. */
|
|
||||||
cond->fallback.waiters_count = 0;
|
|
||||||
|
|
||||||
InitializeCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
|
|
||||||
/* Create an auto-reset event. */
|
|
||||||
cond->fallback.signal_event = CreateEvent(NULL, /* no security */
|
|
||||||
FALSE, /* auto-reset event */
|
|
||||||
FALSE, /* non-signaled initially */
|
|
||||||
NULL); /* unnamed */
|
|
||||||
if (!cond->fallback.signal_event) {
|
|
||||||
err = GetLastError();
|
|
||||||
goto error2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a manual-reset event. */
|
|
||||||
cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */
|
|
||||||
TRUE, /* manual-reset */
|
|
||||||
FALSE, /* non-signaled */
|
|
||||||
NULL); /* unnamed */
|
|
||||||
if (!cond->fallback.broadcast_event) {
|
|
||||||
err = GetLastError();
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
CloseHandle(cond->fallback.signal_event);
|
|
||||||
error2:
|
|
||||||
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
return uv_translate_sys_error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int uv_cond_condvar_init(uv_cond_t* cond) {
|
|
||||||
pInitializeConditionVariable(&cond->cond_var);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_cond_init(uv_cond_t* cond) {
|
int uv_cond_init(uv_cond_t* cond) {
|
||||||
uv__once_init();
|
InitializeConditionVariable(&cond->cond_var);
|
||||||
|
return 0;
|
||||||
if (HAVE_CONDVAR_API())
|
|
||||||
return uv_cond_condvar_init(cond);
|
|
||||||
else
|
|
||||||
return uv_cond_fallback_init(cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_fallback_destroy(uv_cond_t* cond) {
|
|
||||||
if (!CloseHandle(cond->fallback.broadcast_event))
|
|
||||||
abort();
|
|
||||||
if (!CloseHandle(cond->fallback.signal_event))
|
|
||||||
abort();
|
|
||||||
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_condvar_destroy(uv_cond_t* cond) {
|
|
||||||
/* nothing to do */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_cond_destroy(uv_cond_t* cond) {
|
void uv_cond_destroy(uv_cond_t* cond) {
|
||||||
if (HAVE_CONDVAR_API())
|
/* nothing to do */
|
||||||
uv_cond_condvar_destroy(cond);
|
(void) &cond;
|
||||||
else
|
|
||||||
uv_cond_fallback_destroy(cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_fallback_signal(uv_cond_t* cond) {
|
|
||||||
int have_waiters;
|
|
||||||
|
|
||||||
/* Avoid race conditions. */
|
|
||||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
have_waiters = cond->fallback.waiters_count > 0;
|
|
||||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
|
|
||||||
if (have_waiters)
|
|
||||||
SetEvent(cond->fallback.signal_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_condvar_signal(uv_cond_t* cond) {
|
|
||||||
pWakeConditionVariable(&cond->cond_var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_cond_signal(uv_cond_t* cond) {
|
void uv_cond_signal(uv_cond_t* cond) {
|
||||||
if (HAVE_CONDVAR_API())
|
WakeConditionVariable(&cond->cond_var);
|
||||||
uv_cond_condvar_signal(cond);
|
|
||||||
else
|
|
||||||
uv_cond_fallback_signal(cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
|
|
||||||
int have_waiters;
|
|
||||||
|
|
||||||
/* Avoid race conditions. */
|
|
||||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
have_waiters = cond->fallback.waiters_count > 0;
|
|
||||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
|
|
||||||
if (have_waiters)
|
|
||||||
SetEvent(cond->fallback.broadcast_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
|
|
||||||
pWakeAllConditionVariable(&cond->cond_var);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_cond_broadcast(uv_cond_t* cond) {
|
void uv_cond_broadcast(uv_cond_t* cond) {
|
||||||
if (HAVE_CONDVAR_API())
|
WakeAllConditionVariable(&cond->cond_var);
|
||||||
uv_cond_condvar_broadcast(cond);
|
|
||||||
else
|
|
||||||
uv_cond_fallback_broadcast(cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
|
|
||||||
DWORD dwMilliseconds) {
|
|
||||||
DWORD result;
|
|
||||||
int last_waiter;
|
|
||||||
HANDLE handles[2] = {
|
|
||||||
cond->fallback.signal_event,
|
|
||||||
cond->fallback.broadcast_event
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Avoid race conditions. */
|
|
||||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
cond->fallback.waiters_count++;
|
|
||||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
|
|
||||||
/* It's ok to release the <mutex> here since Win32 manual-reset events */
|
|
||||||
/* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */
|
|
||||||
/* bug. */
|
|
||||||
uv_mutex_unlock(mutex);
|
|
||||||
|
|
||||||
/* Wait for either event to become signaled due to <uv_cond_signal> being */
|
|
||||||
/* called or <uv_cond_broadcast> being called. */
|
|
||||||
result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
|
|
||||||
|
|
||||||
EnterCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
cond->fallback.waiters_count--;
|
|
||||||
last_waiter = result == WAIT_OBJECT_0 + 1
|
|
||||||
&& cond->fallback.waiters_count == 0;
|
|
||||||
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
|
|
||||||
|
|
||||||
/* Some thread called <pthread_cond_broadcast>. */
|
|
||||||
if (last_waiter) {
|
|
||||||
/* We're the last waiter to be notified or to stop waiting, so reset the */
|
|
||||||
/* the manual-reset event. */
|
|
||||||
ResetEvent(cond->fallback.broadcast_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reacquire the <mutex>. */
|
|
||||||
uv_mutex_lock(mutex);
|
|
||||||
|
|
||||||
if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (result == WAIT_TIMEOUT)
|
|
||||||
return UV_ETIMEDOUT;
|
|
||||||
|
|
||||||
abort();
|
|
||||||
return -1; /* Satisfy the compiler. */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
|
||||||
if (uv_cond_wait_helper(cond, mutex, INFINITE))
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
|
||||||
if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
|
||||||
if (HAVE_CONDVAR_API())
|
if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
|
||||||
uv_cond_condvar_wait(cond, mutex);
|
abort();
|
||||||
else
|
|
||||||
uv_cond_fallback_wait(cond, mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
|
||||||
static int uv_cond_fallback_timedwait(uv_cond_t* cond,
|
if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
|
||||||
uv_mutex_t* mutex, uint64_t timeout) {
|
|
||||||
return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int uv_cond_condvar_timedwait(uv_cond_t* cond,
|
|
||||||
uv_mutex_t* mutex, uint64_t timeout) {
|
|
||||||
if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
|
|
||||||
return 0;
|
return 0;
|
||||||
if (GetLastError() != ERROR_TIMEOUT)
|
if (GetLastError() != ERROR_TIMEOUT)
|
||||||
abort();
|
abort();
|
||||||
@@ -598,15 +399,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
|
|
||||||
uint64_t timeout) {
|
|
||||||
if (HAVE_CONDVAR_API())
|
|
||||||
return uv_cond_condvar_timedwait(cond, mutex, timeout);
|
|
||||||
else
|
|
||||||
return uv_cond_fallback_timedwait(cond, mutex, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|||||||
@@ -1,195 +0,0 @@
|
|||||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to
|
|
||||||
* deal in the Software without restriction, including without limitation the
|
|
||||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
* sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
* IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#include "uv.h"
|
|
||||||
#include "internal.h"
|
|
||||||
#include "tree.h"
|
|
||||||
#include "handle-inl.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* The number of milliseconds in one second. */
|
|
||||||
#define UV__MILLISEC 1000
|
|
||||||
|
|
||||||
|
|
||||||
void uv_update_time(uv_loop_t* loop) {
|
|
||||||
uint64_t new_time = uv__hrtime(UV__MILLISEC);
|
|
||||||
assert(new_time >= loop->time);
|
|
||||||
loop->time = new_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
|
|
||||||
if (a->due < b->due)
|
|
||||||
return -1;
|
|
||||||
if (a->due > b->due)
|
|
||||||
return 1;
|
|
||||||
/*
|
|
||||||
* compare start_id when both has the same due. start_id is
|
|
||||||
* allocated with loop->timer_counter in uv_timer_start().
|
|
||||||
*/
|
|
||||||
if (a->start_id < b->start_id)
|
|
||||||
return -1;
|
|
||||||
if (a->start_id > b->start_id)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare)
|
|
||||||
|
|
||||||
|
|
||||||
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
|
|
||||||
uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER);
|
|
||||||
handle->timer_cb = NULL;
|
|
||||||
handle->repeat = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) {
|
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
|
||||||
uv__handle_close(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) {
|
|
||||||
uint64_t clamped_timeout;
|
|
||||||
|
|
||||||
clamped_timeout = loop_time + timeout;
|
|
||||||
if (clamped_timeout < timeout)
|
|
||||||
clamped_timeout = (uint64_t) -1;
|
|
||||||
|
|
||||||
return clamped_timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
|
|
||||||
uint64_t repeat) {
|
|
||||||
uv_loop_t* loop = handle->loop;
|
|
||||||
uv_timer_t* old;
|
|
||||||
|
|
||||||
if (timer_cb == NULL)
|
|
||||||
return UV_EINVAL;
|
|
||||||
|
|
||||||
if (uv__is_active(handle))
|
|
||||||
uv_timer_stop(handle);
|
|
||||||
|
|
||||||
handle->timer_cb = timer_cb;
|
|
||||||
handle->due = get_clamped_due_time(loop->time, timeout);
|
|
||||||
handle->repeat = repeat;
|
|
||||||
uv__handle_start(handle);
|
|
||||||
|
|
||||||
/* start_id is the second index to be compared in uv__timer_cmp() */
|
|
||||||
handle->start_id = handle->loop->timer_counter++;
|
|
||||||
|
|
||||||
old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle);
|
|
||||||
assert(old == NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_timer_stop(uv_timer_t* handle) {
|
|
||||||
uv_loop_t* loop = handle->loop;
|
|
||||||
|
|
||||||
if (!uv__is_active(handle))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
RB_REMOVE(uv_timer_tree_s, &loop->timers, handle);
|
|
||||||
uv__handle_stop(handle);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_timer_again(uv_timer_t* handle) {
|
|
||||||
/* If timer_cb is NULL that means that the timer was never started. */
|
|
||||||
if (!handle->timer_cb) {
|
|
||||||
return UV_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle->repeat) {
|
|
||||||
uv_timer_stop(handle);
|
|
||||||
uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
|
|
||||||
assert(handle->type == UV_TIMER);
|
|
||||||
handle->repeat = repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
|
|
||||||
assert(handle->type == UV_TIMER);
|
|
||||||
return handle->repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DWORD uv__next_timeout(const uv_loop_t* loop) {
|
|
||||||
uv_timer_t* timer;
|
|
||||||
int64_t delta;
|
|
||||||
|
|
||||||
/* Check if there are any running timers
|
|
||||||
* Need to cast away const first, since RB_MIN doesn't know what we are
|
|
||||||
* going to do with this return value, it can't be marked const
|
|
||||||
*/
|
|
||||||
timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers);
|
|
||||||
if (timer) {
|
|
||||||
delta = timer->due - loop->time;
|
|
||||||
if (delta >= UINT_MAX - 1) {
|
|
||||||
/* A timeout value of UINT_MAX means infinite, so that's no good. */
|
|
||||||
return UINT_MAX - 1;
|
|
||||||
} else if (delta < 0) {
|
|
||||||
/* Negative timeout values are not allowed */
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return (DWORD)delta;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* No timers */
|
|
||||||
return INFINITE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uv_process_timers(uv_loop_t* loop) {
|
|
||||||
uv_timer_t* timer;
|
|
||||||
|
|
||||||
/* Call timer callbacks */
|
|
||||||
for (timer = RB_MIN(uv_timer_tree_s, &loop->timers);
|
|
||||||
timer != NULL && timer->due <= loop->time;
|
|
||||||
timer = RB_MIN(uv_timer_tree_s, &loop->timers)) {
|
|
||||||
|
|
||||||
uv_timer_stop(timer);
|
|
||||||
uv_timer_again(timer);
|
|
||||||
timer->timer_cb((uv_timer_t*) timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||||
# include "stdint-msvc2008.h"
|
# include "uv/stdint-msvc2008.h"
|
||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -164,7 +164,7 @@ void uv_console_init(void) {
|
|||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
if (uv__tty_console_handle != NULL) {
|
if (uv__tty_console_handle != INVALID_HANDLE_VALUE) {
|
||||||
QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
|
QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
|
||||||
NULL,
|
NULL,
|
||||||
WT_EXECUTELONGFUNCTION);
|
WT_EXECUTELONGFUNCTION);
|
||||||
@@ -172,9 +172,12 @@ void uv_console_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
|
||||||
|
BOOL readable;
|
||||||
|
DWORD NumberOfEvents;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
|
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
|
||||||
|
(void)unused;
|
||||||
|
|
||||||
uv__once_init();
|
uv__once_init();
|
||||||
handle = (HANDLE) uv__get_osfhandle(fd);
|
handle = (HANDLE) uv__get_osfhandle(fd);
|
||||||
@@ -199,14 +202,15 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
|||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readable = GetNumberOfConsoleInputEvents(handle, &NumberOfEvents);
|
||||||
if (!readable) {
|
if (!readable) {
|
||||||
/* Obtain the screen buffer info with the output handle. */
|
/* Obtain the screen buffer info with the output handle. */
|
||||||
if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {
|
if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {
|
||||||
return uv_translate_sys_error(GetLastError());
|
return uv_translate_sys_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain the the tty_output_lock because the virtual window state is */
|
/* Obtain the tty_output_lock because the virtual window state is shared
|
||||||
/* shared between all uv_tty_t handles. */
|
* between all uv_tty_t handles. */
|
||||||
uv_sem_wait(&uv_tty_output_lock);
|
uv_sem_wait(&uv_tty_output_lock);
|
||||||
|
|
||||||
if (uv__vterm_state == UV_UNCHECKED)
|
if (uv__vterm_state == UV_UNCHECKED)
|
||||||
@@ -356,6 +360,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
was_reading = 0;
|
was_reading = 0;
|
||||||
|
alloc_cb = NULL;
|
||||||
|
read_cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_sem_wait(&uv_tty_output_lock);
|
uv_sem_wait(&uv_tty_output_lock);
|
||||||
@@ -382,12 +388,6 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_is_tty(uv_file file) {
|
|
||||||
DWORD result;
|
|
||||||
return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
|
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
|
||||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||||
|
|
||||||
@@ -484,8 +484,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
|
|||||||
bytes = MAX_INPUT_BUFFER_LENGTH;
|
bytes = MAX_INPUT_BUFFER_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At last, unicode! */
|
/* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8
|
||||||
/* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */
|
* codeunits to encode. */
|
||||||
chars = bytes / 3;
|
chars = bytes / 3;
|
||||||
|
|
||||||
status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
|
status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
|
||||||
@@ -620,10 +620,10 @@ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
/* These mappings are the same as Cygwin's. Unmodified and alt-modified */
|
/* These mappings are the same as Cygwin's. Unmodified and alt-modified
|
||||||
/* keypad keys comply with linux console, modifiers comply with xterm */
|
* keypad keys comply with linux console, modifiers comply with xterm
|
||||||
/* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */
|
* modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6.
|
||||||
/* f6..f12 with and without modifiers comply with rxvt. */
|
* f12 with and without modifiers comply with rxvt. */
|
||||||
VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~")
|
VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~")
|
||||||
VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~")
|
VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~")
|
||||||
VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B")
|
VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B")
|
||||||
@@ -706,8 +706,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Windows sends a lot of events that we're not interested in, so buf */
|
/* Windows sends a lot of events that we're not interested in, so buf will be
|
||||||
/* will be allocated on demand, when there's actually something to emit. */
|
* allocated on demand, when there's actually something to emit. */
|
||||||
buf = uv_null_buf_;
|
buf = uv_null_buf_;
|
||||||
buf_used = 0;
|
buf_used = 0;
|
||||||
|
|
||||||
@@ -733,16 +733,17 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore keyup events, unless the left alt key was held and a valid */
|
/* Ignore keyup events, unless the left alt key was held and a valid
|
||||||
/* unicode character was emitted. */
|
* unicode character was emitted. */
|
||||||
if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) ||
|
if (!KEV.bKeyDown &&
|
||||||
KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) {
|
KEV.wVirtualKeyCode != VK_MENU &&
|
||||||
|
KEV.uChar.UnicodeChar != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore keypresses to numpad number keys if the left alt is held */
|
/* Ignore keypresses to numpad number keys if the left alt is held
|
||||||
/* because the user is composing a character, or windows simulating */
|
* because the user is composing a character, or windows simulating this.
|
||||||
/* this. */
|
*/
|
||||||
if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&
|
if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&
|
||||||
!(KEV.dwControlKeyState & ENHANCED_KEY) &&
|
!(KEV.dwControlKeyState & ENHANCED_KEY) &&
|
||||||
(KEV.wVirtualKeyCode == VK_INSERT ||
|
(KEV.wVirtualKeyCode == VK_INSERT ||
|
||||||
@@ -779,8 +780,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prefix with \u033 if alt was held, but alt was not used as part */
|
/* Prefix with \u033 if alt was held, but alt was not used as part a
|
||||||
/* a compose sequence. */
|
* compose sequence. */
|
||||||
if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
|
||||||
&& !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |
|
&& !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |
|
||||||
RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {
|
RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {
|
||||||
@@ -793,8 +794,9 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
if (KEV.uChar.UnicodeChar >= 0xDC00 &&
|
if (KEV.uChar.UnicodeChar >= 0xDC00 &&
|
||||||
KEV.uChar.UnicodeChar < 0xE000) {
|
KEV.uChar.UnicodeChar < 0xE000) {
|
||||||
/* UTF-16 surrogate pair */
|
/* UTF-16 surrogate pair */
|
||||||
WCHAR utf16_buffer[2] = { handle->tty.rd.last_utf16_high_surrogate,
|
WCHAR utf16_buffer[2];
|
||||||
KEV.uChar.UnicodeChar};
|
utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate;
|
||||||
|
utf16_buffer[1] = KEV.uChar.UnicodeChar;
|
||||||
char_len = WideCharToMultiByte(CP_UTF8,
|
char_len = WideCharToMultiByte(CP_UTF8,
|
||||||
0,
|
0,
|
||||||
utf16_buffer,
|
utf16_buffer,
|
||||||
@@ -818,8 +820,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
/* Whatever happened, the last character wasn't a high surrogate. */
|
/* Whatever happened, the last character wasn't a high surrogate. */
|
||||||
handle->tty.rd.last_utf16_high_surrogate = 0;
|
handle->tty.rd.last_utf16_high_surrogate = 0;
|
||||||
|
|
||||||
/* If the utf16 character(s) couldn't be converted something must */
|
/* If the utf16 character(s) couldn't be converted something must be
|
||||||
/* be wrong. */
|
* wrong. */
|
||||||
if (!char_len) {
|
if (!char_len) {
|
||||||
handle->flags &= ~UV_HANDLE_READING;
|
handle->flags &= ~UV_HANDLE_READING;
|
||||||
DECREASE_ACTIVE_COUNT(loop, handle);
|
DECREASE_ACTIVE_COUNT(loop, handle);
|
||||||
@@ -943,21 +945,15 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
handle->read_cb((uv_stream_t*) handle,
|
handle->read_cb((uv_stream_t*) handle,
|
||||||
uv_translate_sys_error(GET_REQ_ERROR(req)),
|
uv_translate_sys_error(GET_REQ_ERROR(req)),
|
||||||
&buf);
|
&buf);
|
||||||
} else {
|
|
||||||
/* The read was cancelled, or whatever we don't care */
|
|
||||||
handle->read_cb((uv_stream_t*) handle, 0, &buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {
|
if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING) &&
|
||||||
/* Read successful */
|
req->u.io.overlapped.InternalHigh != 0) {
|
||||||
/* TODO: read unicode, convert to utf-8 */
|
/* Read successful. TODO: read unicode, convert to utf-8 */
|
||||||
DWORD bytes = req->u.io.overlapped.InternalHigh;
|
DWORD bytes = req->u.io.overlapped.InternalHigh;
|
||||||
handle->read_cb((uv_stream_t*) handle, bytes, &buf);
|
handle->read_cb((uv_stream_t*) handle, bytes, &buf);
|
||||||
} else {
|
|
||||||
handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;
|
|
||||||
handle->read_cb((uv_stream_t*) handle, 0, &buf);
|
|
||||||
}
|
}
|
||||||
|
handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for more input events. */
|
/* Wait for more input events. */
|
||||||
@@ -975,9 +971,9 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
assert(handle->type == UV_TTY);
|
assert(handle->type == UV_TTY);
|
||||||
assert(handle->flags & UV_HANDLE_TTY_READABLE);
|
assert(handle->flags & UV_HANDLE_TTY_READABLE);
|
||||||
|
|
||||||
/* If the read_line_buffer member is zero, it must have been an raw read. */
|
/* If the read_line_buffer member is zero, it must have been an raw read.
|
||||||
/* Otherwise it was a line-buffered read. */
|
* Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a
|
||||||
/* FIXME: This is quite obscure. Use a flag or something. */
|
* flag or something. */
|
||||||
if (handle->tty.rd.read_line_buffer.len == 0) {
|
if (handle->tty.rd.read_line_buffer.len == 0) {
|
||||||
uv_process_tty_read_raw_req(loop, handle, req);
|
uv_process_tty_read_raw_req(loop, handle, req);
|
||||||
} else {
|
} else {
|
||||||
@@ -999,14 +995,14 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
|
|||||||
handle->read_cb = read_cb;
|
handle->read_cb = read_cb;
|
||||||
handle->alloc_cb = alloc_cb;
|
handle->alloc_cb = alloc_cb;
|
||||||
|
|
||||||
/* If reading was stopped and then started again, there could still be a */
|
/* If reading was stopped and then started again, there could still be a read
|
||||||
/* read request pending. */
|
* request pending. */
|
||||||
if (handle->flags & UV_HANDLE_READ_PENDING) {
|
if (handle->flags & UV_HANDLE_READ_PENDING) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maybe the user stopped reading half-way while processing key events. */
|
/* Maybe the user stopped reading half-way while processing key events.
|
||||||
/* Short-circuit if this could be the case. */
|
* Short-circuit if this could be the case. */
|
||||||
if (handle->tty.rd.last_key_len > 0) {
|
if (handle->tty.rd.last_key_len > 0) {
|
||||||
SET_REQ_SUCCESS(&handle->read_req);
|
SET_REQ_SUCCESS(&handle->read_req);
|
||||||
uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
|
uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
|
||||||
@@ -1033,9 +1029,10 @@ int uv_tty_read_stop(uv_tty_t* handle) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_TTY_RAW) {
|
if (handle->flags & UV_HANDLE_TTY_RAW) {
|
||||||
/* Cancel raw read */
|
/* Cancel raw read. Write some bullshit event to force the console wait to
|
||||||
/* Write some bullshit event to force the console wait to return. */
|
* return. */
|
||||||
memset(&record, 0, sizeof record);
|
memset(&record, 0, sizeof record);
|
||||||
|
record.EventType = FOCUS_EVENT;
|
||||||
if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
|
if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
|
||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
@@ -1116,8 +1113,8 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
|
|||||||
uv_tty_virtual_offset = info->dwCursorPosition.Y;
|
uv_tty_virtual_offset = info->dwCursorPosition.Y;
|
||||||
} else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -
|
} else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -
|
||||||
uv_tty_virtual_height + 1) {
|
uv_tty_virtual_height + 1) {
|
||||||
/* If suddenly find the cursor outside of the virtual window, it must */
|
/* If suddenly find the cursor outside of the virtual window, it must have
|
||||||
/* have somehow scrolled. Update the virtual window offset. */
|
* somehow scrolled. Update the virtual window offset. */
|
||||||
uv_tty_virtual_offset = info->dwCursorPosition.Y -
|
uv_tty_virtual_offset = info->dwCursorPosition.Y -
|
||||||
uv_tty_virtual_height + 1;
|
uv_tty_virtual_height + 1;
|
||||||
}
|
}
|
||||||
@@ -1304,8 +1301,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
|
|||||||
x2 = 0;
|
x2 = 0;
|
||||||
x2r = 1;
|
x2r = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Clear to end of row. We pretend the console is 65536 characters wide, */
|
/* Clear to end of row. We pretend the console is 65536 characters wide,
|
||||||
/* uv_tty_make_real_coord will clip it to the actual console width. */
|
* uv_tty_make_real_coord will clip it to the actual console width. */
|
||||||
x2 = 0xffff;
|
x2 = 0xffff;
|
||||||
x2r = 0;
|
x2r = 0;
|
||||||
}
|
}
|
||||||
@@ -1613,8 +1610,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
const uv_buf_t bufs[],
|
const uv_buf_t bufs[],
|
||||||
unsigned int nbufs,
|
unsigned int nbufs,
|
||||||
DWORD* error) {
|
DWORD* error) {
|
||||||
/* We can only write 8k characters at a time. Windows can't handle */
|
/* We can only write 8k characters at a time. Windows can't handle much more
|
||||||
/* much more characters in a single console write anyway. */
|
* characters in a single console write anyway. */
|
||||||
WCHAR utf16_buf[MAX_CONSOLE_CHAR];
|
WCHAR utf16_buf[MAX_CONSOLE_CHAR];
|
||||||
WCHAR* utf16_buffer;
|
WCHAR* utf16_buffer;
|
||||||
DWORD utf16_buf_used = 0;
|
DWORD utf16_buf_used = 0;
|
||||||
@@ -1650,9 +1647,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
unsigned char previous_eol = handle->tty.wr.previous_eol;
|
unsigned char previous_eol = handle->tty.wr.previous_eol;
|
||||||
unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;
|
unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;
|
||||||
|
|
||||||
/* Store the error here. If we encounter an error, stop trying to do i/o */
|
/* Store the error here. If we encounter an error, stop trying to do i/o but
|
||||||
/* but keep parsing the buffer so we leave the parser in a consistent */
|
* keep parsing the buffer so we leave the parser in a consistent state. */
|
||||||
/* state. */
|
|
||||||
*error = ERROR_SUCCESS;
|
*error = ERROR_SUCCESS;
|
||||||
|
|
||||||
utf16_buffer = utf16_buf;
|
utf16_buffer = utf16_buf;
|
||||||
@@ -1700,9 +1696,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
for (j = 0; j < buf.len; j++) {
|
for (j = 0; j < buf.len; j++) {
|
||||||
unsigned char c = buf.base[j];
|
unsigned char c = buf.base[j];
|
||||||
|
|
||||||
/* Run the character through the utf8 decoder We happily accept non */
|
/* Run the character through the utf8 decoder We happily accept non
|
||||||
/* shortest form encodings and invalid code points - there's no real */
|
* shortest form encodings and invalid code points - there's no real harm
|
||||||
/* harm that can be done. */
|
* that can be done. */
|
||||||
if (utf8_bytes_left == 0) {
|
if (utf8_bytes_left == 0) {
|
||||||
/* Read utf-8 start byte */
|
/* Read utf-8 start byte */
|
||||||
DWORD first_zero_bit;
|
DWORD first_zero_bit;
|
||||||
@@ -1742,8 +1738,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
/* Start byte where continuation was expected. */
|
/* Start byte where continuation was expected. */
|
||||||
utf8_bytes_left = 0;
|
utf8_bytes_left = 0;
|
||||||
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
|
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
|
||||||
/* Patch buf offset so this character will be parsed again as a */
|
/* Patch buf offset so this character will be parsed again as a start
|
||||||
/* start byte. */
|
* byte. */
|
||||||
j--;
|
j--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1776,8 +1772,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
case '_':
|
case '_':
|
||||||
case 'P':
|
case 'P':
|
||||||
case ']':
|
case ']':
|
||||||
/* Not supported, but we'll have to parse until we see a stop */
|
/* Not supported, but we'll have to parse until we see a stop code,
|
||||||
/* code, e.g. ESC \ or BEL. */
|
* e. g. ESC \ or BEL. */
|
||||||
ansi_parser_state = ANSI_ST_CONTROL;
|
ansi_parser_state = ANSI_ST_CONTROL;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1859,8 +1855,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* If ANSI_IN_ARG is not set, add another argument and */
|
/* If ANSI_IN_ARG is not set, add another argument and default it
|
||||||
/* default it to 0. */
|
* to 0. */
|
||||||
|
|
||||||
/* Check for too many arguments */
|
/* Check for too many arguments */
|
||||||
if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
|
if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
|
||||||
ansi_parser_state |= ANSI_IGNORE;
|
ansi_parser_state |= ANSI_IGNORE;
|
||||||
@@ -1874,9 +1871,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
|
|
||||||
} else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) &&
|
} else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) &&
|
||||||
handle->tty.wr.ansi_csi_argc == 0) {
|
handle->tty.wr.ansi_csi_argc == 0) {
|
||||||
/* Ignores '?' if it is the first character after CSI[ */
|
/* Ignores '?' if it is the first character after CSI[. This is an
|
||||||
/* This is an extension character from the VT100 codeset */
|
* extension character from the VT100 codeset that is supported and
|
||||||
/* that is supported and used by most ANSI terminals today. */
|
* used by most ANSI terminals today. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
|
} else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
|
||||||
@@ -2006,8 +2003,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* We don't support commands that use private mode characters or */
|
/* We don't support commands that use private mode characters or
|
||||||
/* intermediaries. Ignore the rest of the sequence. */
|
* intermediaries. Ignore the rest of the sequence. */
|
||||||
ansi_parser_state |= ANSI_IGNORE;
|
ansi_parser_state |= ANSI_IGNORE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2020,8 +2017,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (ansi_parser_state & ANSI_ST_CONTROL) {
|
} else if (ansi_parser_state & ANSI_ST_CONTROL) {
|
||||||
/* Unsupported control code */
|
/* Unsupported control code.
|
||||||
/* Ignore everything until we see BEL or ESC \ */
|
* Ignore everything until we see `BEL` or `ESC \`. */
|
||||||
if (ansi_parser_state & ANSI_IN_STRING) {
|
if (ansi_parser_state & ANSI_IN_STRING) {
|
||||||
if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {
|
if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {
|
||||||
if (utf8_codepoint == '"') {
|
if (utf8_codepoint == '"') {
|
||||||
@@ -2055,9 +2052,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */
|
/* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows
|
||||||
/* windows console doesn't really support UTF-16, so just emit the */
|
* console doesn't really support UTF-16, so just emit the replacement
|
||||||
/* replacement character. */
|
* character. */
|
||||||
if (utf8_codepoint > 0xffff) {
|
if (utf8_codepoint > 0xffff) {
|
||||||
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
|
utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
|
||||||
}
|
}
|
||||||
@@ -2071,10 +2068,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
|||||||
utf16_buf[utf16_buf_used++] = L'\r';
|
utf16_buf[utf16_buf_used++] = L'\r';
|
||||||
utf16_buf[utf16_buf_used++] = L'\n';
|
utf16_buf[utf16_buf_used++] = L'\n';
|
||||||
} else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) {
|
} else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) {
|
||||||
/* \n was followed by \r; do not print the \r, since */
|
/* \n was followed by \r; do not print the \r, since the source was
|
||||||
/* the source was either \r\n\r (so the second \r is */
|
* either \r\n\r (so the second \r is redundant) or was \n\r (so the
|
||||||
/* redundant) or was \n\r (so the \n was processed */
|
* \n was processed by the last case and an \r automatically
|
||||||
/* by the last case and an \r automatically inserted). */
|
* inserted). */
|
||||||
} else {
|
} else {
|
||||||
/* \r without \n; print \r as-is. */
|
/* \r without \n; print \r as-is. */
|
||||||
ENSURE_BUFFER_SPACE(1);
|
ENSURE_BUFFER_SPACE(1);
|
||||||
@@ -2182,14 +2179,14 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
|
|||||||
|
|
||||||
void uv_tty_close(uv_tty_t* handle) {
|
void uv_tty_close(uv_tty_t* handle) {
|
||||||
assert(handle->u.fd == -1 || handle->u.fd > 2);
|
assert(handle->u.fd == -1 || handle->u.fd > 2);
|
||||||
|
if (handle->flags & UV_HANDLE_READING)
|
||||||
|
uv_tty_read_stop(handle);
|
||||||
|
|
||||||
if (handle->u.fd == -1)
|
if (handle->u.fd == -1)
|
||||||
CloseHandle(handle->handle);
|
CloseHandle(handle->handle);
|
||||||
else
|
else
|
||||||
close(handle->u.fd);
|
close(handle->u.fd);
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_READING)
|
|
||||||
uv_tty_read_stop(handle);
|
|
||||||
|
|
||||||
handle->u.fd = -1;
|
handle->u.fd = -1;
|
||||||
handle->handle = INVALID_HANDLE_VALUE;
|
handle->handle = INVALID_HANDLE_VALUE;
|
||||||
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
|
||||||
@@ -2209,7 +2206,7 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
|
|||||||
|
|
||||||
/* TTY shutdown is really just a no-op */
|
/* TTY shutdown is really just a no-op */
|
||||||
if (handle->stream.conn.shutdown_req->cb) {
|
if (handle->stream.conn.shutdown_req->cb) {
|
||||||
if (handle->flags & UV__HANDLE_CLOSING) {
|
if (handle->flags & UV_HANDLE_CLOSING) {
|
||||||
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);
|
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);
|
||||||
} else {
|
} else {
|
||||||
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);
|
handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);
|
||||||
@@ -2222,10 +2219,10 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handle->flags & UV__HANDLE_CLOSING &&
|
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||||
handle->reqs_pending == 0) {
|
handle->reqs_pending == 0) {
|
||||||
/* The wait handle used for raw reading should be unregistered when the */
|
/* The wait handle used for raw reading should be unregistered when the
|
||||||
/* wait callback runs. */
|
* wait callback runs. */
|
||||||
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
|
assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
|
||||||
handle->tty.rd.read_raw_wait == NULL);
|
handle->tty.rd.read_raw_wait == NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
|
|||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Associate it with the I/O completion port. */
|
/* Associate it with the I/O completion port. Use uv_handle_t pointer as
|
||||||
/* Use uv_handle_t pointer as completion key. */
|
* completion key. */
|
||||||
if (CreateIoCompletionPort((HANDLE)socket,
|
if (CreateIoCompletionPort((HANDLE)socket,
|
||||||
loop->iocp,
|
loop->iocp,
|
||||||
(ULONG_PTR)socket,
|
(ULONG_PTR)socket,
|
||||||
@@ -83,31 +83,28 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
|
|||||||
return GetLastError();
|
return GetLastError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pSetFileCompletionNotificationModes) {
|
/* All known Windows that support SetFileCompletionNotificationModes have a
|
||||||
/* All known Windows that support SetFileCompletionNotificationModes */
|
* bug that makes it impossible to use this function in conjunction with
|
||||||
/* have a bug that makes it impossible to use this function in */
|
* datagram sockets. We can work around that but only if the user is using
|
||||||
/* conjunction with datagram sockets. We can work around that but only */
|
* the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
|
||||||
/* if the user is using the default UDP driver (AFD) and has no other */
|
* we check whether that is the case. */
|
||||||
/* LSPs stacked on top. Here we check whether that is the case. */
|
opt_len = (int) sizeof info;
|
||||||
opt_len = (int) sizeof info;
|
if (getsockopt(
|
||||||
if (getsockopt(socket,
|
socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
|
||||||
SOL_SOCKET,
|
SOCKET_ERROR) {
|
||||||
SO_PROTOCOL_INFOW,
|
return GetLastError();
|
||||||
(char*) &info,
|
}
|
||||||
&opt_len) == SOCKET_ERROR) {
|
|
||||||
return GetLastError();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.ProtocolChain.ChainLen == 1) {
|
if (info.ProtocolChain.ChainLen == 1) {
|
||||||
if (pSetFileCompletionNotificationModes((HANDLE)socket,
|
if (SetFileCompletionNotificationModes(
|
||||||
FILE_SKIP_SET_EVENT_ON_HANDLE |
|
(HANDLE) socket,
|
||||||
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
|
FILE_SKIP_SET_EVENT_ON_HANDLE |
|
||||||
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
|
||||||
handle->func_wsarecv = uv_wsarecv_workaround;
|
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
|
||||||
handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
|
handle->func_wsarecv = uv_wsarecv_workaround;
|
||||||
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
|
handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
|
||||||
return GetLastError();
|
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
|
||||||
}
|
return GetLastError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +188,7 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
|
|||||||
|
|
||||||
|
|
||||||
void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
|
void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
|
||||||
if (handle->flags & UV__HANDLE_CLOSING &&
|
if (handle->flags & UV_HANDLE_CLOSING &&
|
||||||
handle->reqs_pending == 0) {
|
handle->reqs_pending == 0) {
|
||||||
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
assert(!(handle->flags & UV_HANDLE_CLOSED));
|
||||||
uv__handle_close(handle);
|
uv__handle_close(handle);
|
||||||
@@ -245,12 +242,12 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
|
|||||||
handle->flags |= UV_HANDLE_IPV6;
|
handle->flags |= UV_HANDLE_IPV6;
|
||||||
|
|
||||||
if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
|
if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
|
||||||
/* On windows IPV6ONLY is on by default. */
|
/* On windows IPV6ONLY is on by default. If the user doesn't specify it
|
||||||
/* If the user doesn't specify it libuv turns it off. */
|
* libuv turns it off. */
|
||||||
|
|
||||||
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
|
/* TODO: how to handle errors? This may fail if there is no ipv4 stack
|
||||||
/* available, or when run on XP/2003 which have no support for dualstack */
|
* available, or when run on XP/2003 which have no support for dualstack
|
||||||
/* sockets. For now we're silently ignoring the error. */
|
* sockets. For now we're silently ignoring the error. */
|
||||||
setsockopt(handle->socket,
|
setsockopt(handle->socket,
|
||||||
IPPROTO_IPV6,
|
IPPROTO_IPV6,
|
||||||
IPV6_V6ONLY,
|
IPV6_V6ONLY,
|
||||||
@@ -369,7 +366,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (handle->flags & UV_HANDLE_READING) {
|
if (handle->flags & UV_HANDLE_READING) {
|
||||||
return WSAEALREADY;
|
return UV_EALREADY;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = uv_udp_maybe_bind(handle,
|
err = uv_udp_maybe_bind(handle,
|
||||||
@@ -377,7 +374,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
|
|||||||
sizeof(uv_addr_ip4_any_),
|
sizeof(uv_addr_ip4_any_),
|
||||||
0);
|
0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return uv_translate_sys_error(err);
|
||||||
|
|
||||||
handle->flags |= UV_HANDLE_READING;
|
handle->flags |= UV_HANDLE_READING;
|
||||||
INCREASE_ACTIVE_COUNT(loop, handle);
|
INCREASE_ACTIVE_COUNT(loop, handle);
|
||||||
@@ -386,8 +383,8 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
|
|||||||
handle->recv_cb = recv_cb;
|
handle->recv_cb = recv_cb;
|
||||||
handle->alloc_cb = alloc_cb;
|
handle->alloc_cb = alloc_cb;
|
||||||
|
|
||||||
/* If reading was stopped and then started again, there could still be a */
|
/* If reading was stopped and then started again, there could still be a recv
|
||||||
/* recv request pending. */
|
* request pending. */
|
||||||
if (!(handle->flags & UV_HANDLE_READ_PENDING))
|
if (!(handle->flags & UV_HANDLE_READ_PENDING))
|
||||||
uv_udp_queue_recv(loop, handle);
|
uv_udp_queue_recv(loop, handle);
|
||||||
|
|
||||||
@@ -467,19 +464,19 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
|
|||||||
if (!REQ_SUCCESS(req)) {
|
if (!REQ_SUCCESS(req)) {
|
||||||
DWORD err = GET_REQ_SOCK_ERROR(req);
|
DWORD err = GET_REQ_SOCK_ERROR(req);
|
||||||
if (err == WSAEMSGSIZE) {
|
if (err == WSAEMSGSIZE) {
|
||||||
/* Not a real error, it just indicates that the received packet */
|
/* Not a real error, it just indicates that the received packet was
|
||||||
/* was bigger than the receive buffer. */
|
* bigger than the receive buffer. */
|
||||||
} else if (err == WSAECONNRESET || err == WSAENETRESET) {
|
} else if (err == WSAECONNRESET || err == WSAENETRESET) {
|
||||||
/* A previous sendto operation failed; ignore this error. If */
|
/* A previous sendto operation failed; ignore this error. If zero-reading
|
||||||
/* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */
|
* we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
|
||||||
/* MSG_PEEK flag to clear out the error queue. For nonzero reads, */
|
* clear out the error queue. For nonzero reads, immediately queue a new
|
||||||
/* immediately queue a new receive. */
|
* receive. */
|
||||||
if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
|
if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* A real error occurred. Report the error to the user only if we're */
|
/* A real error occurred. Report the error to the user only if we're
|
||||||
/* currently reading. */
|
* currently reading. */
|
||||||
if (handle->flags & UV_HANDLE_READING) {
|
if (handle->flags & UV_HANDLE_READING) {
|
||||||
uv_udp_recv_stop(handle);
|
uv_udp_recv_stop(handle);
|
||||||
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
|
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
|
||||||
@@ -503,8 +500,8 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
|
|||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
int from_len;
|
int from_len;
|
||||||
|
|
||||||
/* Do a nonblocking receive */
|
/* Do a nonblocking receive.
|
||||||
/* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
|
* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
|
||||||
buf = uv_buf_init(NULL, 0);
|
buf = uv_buf_init(NULL, 0);
|
||||||
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
|
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
|
||||||
if (buf.base == NULL || buf.len == 0) {
|
if (buf.base == NULL || buf.len == 0) {
|
||||||
@@ -741,7 +738,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
|
|||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(handle->flags & UV_HANDLE_BOUND))
|
if (handle->socket == INVALID_SOCKET)
|
||||||
return UV_EBADF;
|
return UV_EBADF;
|
||||||
|
|
||||||
if (addr_st.ss_family == AF_INET) {
|
if (addr_st.ss_family == AF_INET) {
|
||||||
@@ -772,7 +769,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
|
|||||||
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
|
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
|
||||||
BOOL optval = (BOOL) value;
|
BOOL optval = (BOOL) value;
|
||||||
|
|
||||||
if (!(handle->flags & UV_HANDLE_BOUND))
|
if (handle->socket == INVALID_SOCKET)
|
||||||
return UV_EBADF;
|
return UV_EBADF;
|
||||||
|
|
||||||
if (setsockopt(handle->socket,
|
if (setsockopt(handle->socket,
|
||||||
@@ -818,7 +815,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
|
|||||||
return UV_EINVAL; \
|
return UV_EINVAL; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
if (!(handle->flags & UV_HANDLE_BOUND)) \
|
if (handle->socket == INVALID_SOCKET) \
|
||||||
return UV_EBADF; \
|
return UV_EBADF; \
|
||||||
\
|
\
|
||||||
if (!(handle->flags & UV_HANDLE_IPV6)) { \
|
if (!(handle->flags & UV_HANDLE_IPV6)) { \
|
||||||
|
|||||||
@@ -74,10 +74,6 @@
|
|||||||
static char *process_title;
|
static char *process_title;
|
||||||
static CRITICAL_SECTION process_title_lock;
|
static CRITICAL_SECTION process_title_lock;
|
||||||
|
|
||||||
/* Cached copy of the process id, written once. */
|
|
||||||
static DWORD current_pid = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* Interval (in seconds) of the high-resolution clock. */
|
/* Interval (in seconds) of the high-resolution clock. */
|
||||||
static double hrtime_interval_ = 0;
|
static double hrtime_interval_ = 0;
|
||||||
|
|
||||||
@@ -149,8 +145,8 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
|
|||||||
|
|
||||||
uv__free(utf16_buffer);
|
uv__free(utf16_buffer);
|
||||||
|
|
||||||
/* utf8_len *does* include the terminating null at this point, but the */
|
/* utf8_len *does* include the terminating null at this point, but the
|
||||||
/* returned size shouldn't. */
|
* returned size shouldn't. */
|
||||||
*size_ptr = utf8_len - 1;
|
*size_ptr = utf8_len - 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -173,16 +169,16 @@ int uv_cwd(char* buffer, size_t* size) {
|
|||||||
if (utf16_len == 0) {
|
if (utf16_len == 0) {
|
||||||
return uv_translate_sys_error(GetLastError());
|
return uv_translate_sys_error(GetLastError());
|
||||||
} else if (utf16_len > MAX_PATH) {
|
} else if (utf16_len > MAX_PATH) {
|
||||||
/* This should be impossible; however the CRT has a code path to deal */
|
/* This should be impossible; however the CRT has a code path to deal with
|
||||||
/* with this scenario, so I added a check anyway. */
|
* this scenario, so I added a check anyway. */
|
||||||
return UV_EIO;
|
return UV_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* utf16_len contains the length, *not* including the terminating null. */
|
/* utf16_len contains the length, *not* including the terminating null. */
|
||||||
utf16_buffer[utf16_len] = L'\0';
|
utf16_buffer[utf16_len] = L'\0';
|
||||||
|
|
||||||
/* The returned directory should not have a trailing slash, unless it */
|
/* The returned directory should not have a trailing slash, unless it points
|
||||||
/* points at a drive root, like c:\. Remove it if needed.*/
|
* at a drive root, like c:\. Remove it if needed. */
|
||||||
if (utf16_buffer[utf16_len - 1] == L'\\' &&
|
if (utf16_buffer[utf16_len - 1] == L'\\' &&
|
||||||
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
|
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
|
||||||
utf16_len--;
|
utf16_len--;
|
||||||
@@ -239,9 +235,9 @@ int uv_chdir(const char* dir) {
|
|||||||
utf16_buffer,
|
utf16_buffer,
|
||||||
MAX_PATH) == 0) {
|
MAX_PATH) == 0) {
|
||||||
DWORD error = GetLastError();
|
DWORD error = GetLastError();
|
||||||
/* The maximum length of the current working directory is 260 chars, */
|
/* The maximum length of the current working directory is 260 chars,
|
||||||
/* including terminating null. If it doesn't fit, the path name must be */
|
* including terminating null. If it doesn't fit, the path name must be too
|
||||||
/* too long. */
|
* long. */
|
||||||
if (error == ERROR_INSUFFICIENT_BUFFER) {
|
if (error == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
return UV_ENAMETOOLONG;
|
return UV_ENAMETOOLONG;
|
||||||
} else {
|
} else {
|
||||||
@@ -253,9 +249,9 @@ int uv_chdir(const char* dir) {
|
|||||||
return uv_translate_sys_error(GetLastError());
|
return uv_translate_sys_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Windows stores the drive-local path in an "hidden" environment variable, */
|
/* Windows stores the drive-local path in an "hidden" environment variable,
|
||||||
/* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
|
* which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
|
||||||
/* update this, so we'll have to do it. */
|
* this, so we'll have to do it. */
|
||||||
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
|
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
|
||||||
if (utf16_len == 0) {
|
if (utf16_len == 0) {
|
||||||
return uv_translate_sys_error(GetLastError());
|
return uv_translate_sys_error(GetLastError());
|
||||||
@@ -263,8 +259,8 @@ int uv_chdir(const char* dir) {
|
|||||||
return UV_EIO;
|
return UV_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The returned directory should not have a trailing slash, unless it */
|
/* The returned directory should not have a trailing slash, unless it points
|
||||||
/* points at a drive root, like c:\. Remove it if needed. */
|
* at a drive root, like c:\. Remove it if needed. */
|
||||||
if (utf16_buffer[utf16_len - 1] == L'\\' &&
|
if (utf16_buffer[utf16_len - 1] == L'\\' &&
|
||||||
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
|
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
|
||||||
utf16_len--;
|
utf16_len--;
|
||||||
@@ -272,8 +268,8 @@ int uv_chdir(const char* dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (utf16_len < 2 || utf16_buffer[1] != L':') {
|
if (utf16_len < 2 || utf16_buffer[1] != L':') {
|
||||||
/* Doesn't look like a drive letter could be there - probably an UNC */
|
/* Doesn't look like a drive letter could be there - probably an UNC path.
|
||||||
/* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
|
* TODO: Need to handle win32 namespaces like \\?\C:\ ? */
|
||||||
drive_letter = 0;
|
drive_letter = 0;
|
||||||
} else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
|
} else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
|
||||||
drive_letter = utf16_buffer[0];
|
drive_letter = utf16_buffer[0];
|
||||||
@@ -359,14 +355,6 @@ uv_pid_t uv_os_getppid(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_current_pid(void) {
|
|
||||||
if (current_pid == 0) {
|
|
||||||
current_pid = GetCurrentProcessId();
|
|
||||||
}
|
|
||||||
return current_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char** uv_setup_args(int argc, char** argv) {
|
char** uv_setup_args(int argc, char** argv) {
|
||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
@@ -828,6 +816,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
int is_vista_or_greater;
|
int is_vista_or_greater;
|
||||||
ULONG flags;
|
ULONG flags;
|
||||||
|
|
||||||
|
*addresses_ptr = NULL;
|
||||||
|
*count_ptr = 0;
|
||||||
|
|
||||||
is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
|
is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
|
||||||
if (is_vista_or_greater) {
|
if (is_vista_or_greater) {
|
||||||
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
|
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
|
||||||
@@ -842,17 +833,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Fetch the size of the adapters reported by windows, and then get the */
|
/* Fetch the size of the adapters reported by windows, and then get the list
|
||||||
/* list itself. */
|
* itself. */
|
||||||
win_address_buf_size = 0;
|
win_address_buf_size = 0;
|
||||||
win_address_buf = NULL;
|
win_address_buf = NULL;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ULONG r;
|
ULONG r;
|
||||||
|
|
||||||
/* If win_address_buf is 0, then GetAdaptersAddresses will fail with */
|
/* If win_address_buf is 0, then GetAdaptersAddresses will fail with.
|
||||||
/* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */
|
* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in
|
||||||
/* win_address_buf_size. */
|
* win_address_buf_size. */
|
||||||
r = GetAdaptersAddresses(AF_UNSPEC,
|
r = GetAdaptersAddresses(AF_UNSPEC,
|
||||||
flags,
|
flags,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -866,8 +857,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case ERROR_BUFFER_OVERFLOW:
|
case ERROR_BUFFER_OVERFLOW:
|
||||||
/* This happens when win_address_buf is NULL or too small to hold */
|
/* This happens when win_address_buf is NULL or too small to hold all
|
||||||
/* all adapters. */
|
* adapters. */
|
||||||
win_address_buf = uv__malloc(win_address_buf_size);
|
win_address_buf = uv__malloc(win_address_buf_size);
|
||||||
if (win_address_buf == NULL)
|
if (win_address_buf == NULL)
|
||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
@@ -901,15 +892,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
return UV_ENOBUFS;
|
return UV_ENOBUFS;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Other (unspecified) errors can happen, but we don't have any */
|
/* Other (unspecified) errors can happen, but we don't have any special
|
||||||
/* special meaning for them. */
|
* meaning for them. */
|
||||||
assert(r != ERROR_SUCCESS);
|
assert(r != ERROR_SUCCESS);
|
||||||
return uv_translate_sys_error(r);
|
return uv_translate_sys_error(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count the number of enabled interfaces and compute how much space is */
|
/* Count the number of enabled interfaces and compute how much space is
|
||||||
/* needed to store their info. */
|
* needed to store their info. */
|
||||||
count = 0;
|
count = 0;
|
||||||
uv_address_buf_size = 0;
|
uv_address_buf_size = 0;
|
||||||
|
|
||||||
@@ -919,9 +910,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
|
IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
|
||||||
int name_size;
|
int name_size;
|
||||||
|
|
||||||
/* Interfaces that are not 'up' should not be reported. Also skip */
|
/* Interfaces that are not 'up' should not be reported. Also skip
|
||||||
/* interfaces that have no associated unicast address, as to avoid */
|
* interfaces that have no associated unicast address, as to avoid
|
||||||
/* allocating space for the name for this interface. */
|
* allocating space for the name for this interface. */
|
||||||
if (adapter->OperStatus != IfOperStatusUp ||
|
if (adapter->OperStatus != IfOperStatusUp ||
|
||||||
adapter->FirstUnicastAddress == NULL)
|
adapter->FirstUnicastAddress == NULL)
|
||||||
continue;
|
continue;
|
||||||
@@ -941,8 +932,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
}
|
}
|
||||||
uv_address_buf_size += name_size;
|
uv_address_buf_size += name_size;
|
||||||
|
|
||||||
/* Count the number of addresses associated with this interface, and */
|
/* Count the number of addresses associated with this interface, and
|
||||||
/* compute the size. */
|
* compute the size. */
|
||||||
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
|
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
|
||||||
adapter->FirstUnicastAddress;
|
adapter->FirstUnicastAddress;
|
||||||
unicast_address != NULL;
|
unicast_address != NULL;
|
||||||
@@ -959,8 +950,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
|
|||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the start of the uv_interface_address_t array, and the place in */
|
/* Compute the start of the uv_interface_address_t array, and the place in
|
||||||
/* the buffer where the interface names will be stored. */
|
* the buffer where the interface names will be stored. */
|
||||||
uv_address = uv_address_buf;
|
uv_address = uv_address_buf;
|
||||||
name_buf = (char*) (uv_address_buf + count);
|
name_buf = (char*) (uv_address_buf + count);
|
||||||
|
|
||||||
@@ -1199,8 +1190,8 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
|
|||||||
return UV_EIO;
|
return UV_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The returned directory should not have a trailing slash, unless it */
|
/* The returned directory should not have a trailing slash, unless it points
|
||||||
/* points at a drive root, like c:\. Remove it if needed.*/
|
* at a drive root, like c:\. Remove it if needed. */
|
||||||
if (path[len - 1] == L'\\' &&
|
if (path[len - 1] == L'\\' &&
|
||||||
!(len == 3 && path[1] == L':')) {
|
!(len == 3 && path[1] == L':')) {
|
||||||
len--;
|
len--;
|
||||||
@@ -1542,3 +1533,214 @@ int uv_os_gethostname(char* buffer, size_t* size) {
|
|||||||
*size = len;
|
*size = len;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
*handle = GetCurrentProcess();
|
||||||
|
else
|
||||||
|
*handle = OpenProcess(access, FALSE, pid);
|
||||||
|
|
||||||
|
if (*handle == NULL) {
|
||||||
|
r = GetLastError();
|
||||||
|
|
||||||
|
if (r == ERROR_INVALID_PARAMETER)
|
||||||
|
return UV_ESRCH;
|
||||||
|
else
|
||||||
|
return uv_translate_sys_error(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_getpriority(uv_pid_t pid, int* priority) {
|
||||||
|
HANDLE handle;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (priority == NULL)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
|
||||||
|
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = GetPriorityClass(handle);
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
r = uv_translate_sys_error(GetLastError());
|
||||||
|
} else {
|
||||||
|
/* Map Windows priority classes to Unix nice values. */
|
||||||
|
if (r == REALTIME_PRIORITY_CLASS)
|
||||||
|
*priority = UV_PRIORITY_HIGHEST;
|
||||||
|
else if (r == HIGH_PRIORITY_CLASS)
|
||||||
|
*priority = UV_PRIORITY_HIGH;
|
||||||
|
else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
|
||||||
|
*priority = UV_PRIORITY_ABOVE_NORMAL;
|
||||||
|
else if (r == NORMAL_PRIORITY_CLASS)
|
||||||
|
*priority = UV_PRIORITY_NORMAL;
|
||||||
|
else if (r == BELOW_NORMAL_PRIORITY_CLASS)
|
||||||
|
*priority = UV_PRIORITY_BELOW_NORMAL;
|
||||||
|
else /* IDLE_PRIORITY_CLASS */
|
||||||
|
*priority = UV_PRIORITY_LOW;
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(handle);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_setpriority(uv_pid_t pid, int priority) {
|
||||||
|
HANDLE handle;
|
||||||
|
int priority_class;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Map Unix nice values to Windows priority classes. */
|
||||||
|
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
|
||||||
|
return UV_EINVAL;
|
||||||
|
else if (priority < UV_PRIORITY_HIGH)
|
||||||
|
priority_class = REALTIME_PRIORITY_CLASS;
|
||||||
|
else if (priority < UV_PRIORITY_ABOVE_NORMAL)
|
||||||
|
priority_class = HIGH_PRIORITY_CLASS;
|
||||||
|
else if (priority < UV_PRIORITY_NORMAL)
|
||||||
|
priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
|
||||||
|
else if (priority < UV_PRIORITY_BELOW_NORMAL)
|
||||||
|
priority_class = NORMAL_PRIORITY_CLASS;
|
||||||
|
else if (priority < UV_PRIORITY_LOW)
|
||||||
|
priority_class = BELOW_NORMAL_PRIORITY_CLASS;
|
||||||
|
else
|
||||||
|
priority_class = IDLE_PRIORITY_CLASS;
|
||||||
|
|
||||||
|
r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
|
||||||
|
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (SetPriorityClass(handle, priority_class) == 0)
|
||||||
|
r = uv_translate_sys_error(GetLastError());
|
||||||
|
|
||||||
|
CloseHandle(handle);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_os_uname(uv_utsname_t* buffer) {
|
||||||
|
/* Implementation loosely based on
|
||||||
|
https://github.com/gagern/gnulib/blob/master/lib/uname.c */
|
||||||
|
OSVERSIONINFOW os_info;
|
||||||
|
SYSTEM_INFO system_info;
|
||||||
|
int processor_level;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (buffer == NULL)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
uv__once_init();
|
||||||
|
os_info.dwOSVersionInfoSize = sizeof(os_info);
|
||||||
|
os_info.szCSDVersion[0] = L'\0';
|
||||||
|
|
||||||
|
/* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()
|
||||||
|
if RtlGetVersion() is not available. */
|
||||||
|
if (pRtlGetVersion) {
|
||||||
|
pRtlGetVersion(&os_info);
|
||||||
|
} else {
|
||||||
|
/* Silence GetVersionEx() deprecation warning. */
|
||||||
|
#pragma warning(suppress : 4996)
|
||||||
|
if (GetVersionExW(&os_info) == 0) {
|
||||||
|
r = uv_translate_sys_error(GetLastError());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the version field. */
|
||||||
|
if (WideCharToMultiByte(CP_UTF8,
|
||||||
|
0,
|
||||||
|
os_info.szCSDVersion,
|
||||||
|
-1,
|
||||||
|
buffer->version,
|
||||||
|
sizeof(buffer->version),
|
||||||
|
NULL,
|
||||||
|
NULL) == 0) {
|
||||||
|
r = uv_translate_sys_error(GetLastError());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the sysname field. */
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
r = snprintf(buffer->sysname,
|
||||||
|
sizeof(buffer->sysname),
|
||||||
|
"MINGW32_NT-%u.%u",
|
||||||
|
(unsigned int) os_info.dwMajorVersion,
|
||||||
|
(unsigned int) os_info.dwMinorVersion);
|
||||||
|
assert(r < sizeof(buffer->sysname));
|
||||||
|
#else
|
||||||
|
uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Populate the release field. */
|
||||||
|
r = snprintf(buffer->release,
|
||||||
|
sizeof(buffer->release),
|
||||||
|
"%d.%d.%d",
|
||||||
|
(unsigned int) os_info.dwMajorVersion,
|
||||||
|
(unsigned int) os_info.dwMinorVersion,
|
||||||
|
(unsigned int) os_info.dwBuildNumber);
|
||||||
|
assert(r < sizeof(buffer->release));
|
||||||
|
|
||||||
|
/* Populate the machine field. */
|
||||||
|
GetSystemInfo(&system_info);
|
||||||
|
|
||||||
|
switch (system_info.wProcessorArchitecture) {
|
||||||
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||||
|
uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_IA64:
|
||||||
|
uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||||
|
uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));
|
||||||
|
|
||||||
|
if (system_info.wProcessorLevel > 3) {
|
||||||
|
processor_level = system_info.wProcessorLevel < 6 ?
|
||||||
|
system_info.wProcessorLevel : 6;
|
||||||
|
buffer->machine[1] = '0' + processor_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
|
||||||
|
uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_MIPS:
|
||||||
|
uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_ALPHA:
|
||||||
|
case PROCESSOR_ARCHITECTURE_ALPHA64:
|
||||||
|
uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_PPC:
|
||||||
|
uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_SHX:
|
||||||
|
uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
case PROCESSOR_ARCHITECTURE_ARM:
|
||||||
|
uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
buffer->sysname[0] = '\0';
|
||||||
|
buffer->release[0] = '\0';
|
||||||
|
buffer->version[0] = '\0';
|
||||||
|
buffer->machine[0] = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Ntdll function pointers */
|
/* Ntdll function pointers */
|
||||||
|
sRtlGetVersion pRtlGetVersion;
|
||||||
sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||||
sNtDeviceIoControlFile pNtDeviceIoControlFile;
|
sNtDeviceIoControlFile pNtDeviceIoControlFile;
|
||||||
sNtQueryInformationFile pNtQueryInformationFile;
|
sNtQueryInformationFile pNtQueryInformationFile;
|
||||||
@@ -34,20 +35,8 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
|
|||||||
sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
||||||
sNtQuerySystemInformation pNtQuerySystemInformation;
|
sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
|
|
||||||
|
|
||||||
/* Kernel32 function pointers */
|
/* Kernel32 function pointers */
|
||||||
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||||
sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
|
|
||||||
sCreateSymbolicLinkW pCreateSymbolicLinkW;
|
|
||||||
sCancelIoEx pCancelIoEx;
|
|
||||||
sInitializeConditionVariable pInitializeConditionVariable;
|
|
||||||
sSleepConditionVariableCS pSleepConditionVariableCS;
|
|
||||||
sSleepConditionVariableSRW pSleepConditionVariableSRW;
|
|
||||||
sWakeAllConditionVariable pWakeAllConditionVariable;
|
|
||||||
sWakeConditionVariable pWakeConditionVariable;
|
|
||||||
sCancelSynchronousIo pCancelSynchronousIo;
|
|
||||||
sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
|
||||||
|
|
||||||
|
|
||||||
/* Powrprof.dll function pointer */
|
/* Powrprof.dll function pointer */
|
||||||
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||||
@@ -55,22 +44,21 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
|||||||
/* User32.dll function pointer */
|
/* User32.dll function pointer */
|
||||||
sSetWinEventHook pSetWinEventHook;
|
sSetWinEventHook pSetWinEventHook;
|
||||||
|
|
||||||
/* iphlpapi.dll function pointer */
|
|
||||||
sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL;
|
|
||||||
sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL;
|
|
||||||
|
|
||||||
void uv_winapi_init(void) {
|
void uv_winapi_init(void) {
|
||||||
HMODULE ntdll_module;
|
HMODULE ntdll_module;
|
||||||
HMODULE kernel32_module;
|
|
||||||
HMODULE powrprof_module;
|
HMODULE powrprof_module;
|
||||||
HMODULE user32_module;
|
HMODULE user32_module;
|
||||||
HMODULE iphlpapi_module;
|
HMODULE kernel32_module;
|
||||||
|
|
||||||
ntdll_module = GetModuleHandleA("ntdll.dll");
|
ntdll_module = GetModuleHandleA("ntdll.dll");
|
||||||
if (ntdll_module == NULL) {
|
if (ntdll_module == NULL) {
|
||||||
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pRtlGetVersion = (sRtlGetVersion) GetProcAddress(ntdll_module,
|
||||||
|
"RtlGetVersion");
|
||||||
|
|
||||||
pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(
|
pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(
|
||||||
ntdll_module,
|
ntdll_module,
|
||||||
"RtlNtStatusToDosError");
|
"RtlNtStatusToDosError");
|
||||||
@@ -127,37 +115,6 @@ void uv_winapi_init(void) {
|
|||||||
kernel32_module,
|
kernel32_module,
|
||||||
"GetQueuedCompletionStatusEx");
|
"GetQueuedCompletionStatusEx");
|
||||||
|
|
||||||
pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes)
|
|
||||||
GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes");
|
|
||||||
|
|
||||||
pCreateSymbolicLinkW = (sCreateSymbolicLinkW)
|
|
||||||
GetProcAddress(kernel32_module, "CreateSymbolicLinkW");
|
|
||||||
|
|
||||||
pCancelIoEx = (sCancelIoEx)
|
|
||||||
GetProcAddress(kernel32_module, "CancelIoEx");
|
|
||||||
|
|
||||||
pInitializeConditionVariable = (sInitializeConditionVariable)
|
|
||||||
GetProcAddress(kernel32_module, "InitializeConditionVariable");
|
|
||||||
|
|
||||||
pSleepConditionVariableCS = (sSleepConditionVariableCS)
|
|
||||||
GetProcAddress(kernel32_module, "SleepConditionVariableCS");
|
|
||||||
|
|
||||||
pSleepConditionVariableSRW = (sSleepConditionVariableSRW)
|
|
||||||
GetProcAddress(kernel32_module, "SleepConditionVariableSRW");
|
|
||||||
|
|
||||||
pWakeAllConditionVariable = (sWakeAllConditionVariable)
|
|
||||||
GetProcAddress(kernel32_module, "WakeAllConditionVariable");
|
|
||||||
|
|
||||||
pWakeConditionVariable = (sWakeConditionVariable)
|
|
||||||
GetProcAddress(kernel32_module, "WakeConditionVariable");
|
|
||||||
|
|
||||||
pCancelSynchronousIo = (sCancelSynchronousIo)
|
|
||||||
GetProcAddress(kernel32_module, "CancelSynchronousIo");
|
|
||||||
|
|
||||||
pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
|
|
||||||
GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
|
|
||||||
|
|
||||||
|
|
||||||
powrprof_module = LoadLibraryA("powrprof.dll");
|
powrprof_module = LoadLibraryA("powrprof.dll");
|
||||||
if (powrprof_module != NULL) {
|
if (powrprof_module != NULL) {
|
||||||
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
|
pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
|
||||||
@@ -170,11 +127,4 @@ void uv_winapi_init(void) {
|
|||||||
GetProcAddress(user32_module, "SetWinEventHook");
|
GetProcAddress(user32_module, "SetWinEventHook");
|
||||||
}
|
}
|
||||||
|
|
||||||
iphlpapi_module = LoadLibraryA("iphlpapi.dll");
|
|
||||||
if (iphlpapi_module != NULL) {
|
|
||||||
pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid)
|
|
||||||
GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid");
|
|
||||||
pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW)
|
|
||||||
GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4076,8 +4076,8 @@
|
|||||||
# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L)
|
# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */
|
/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK
|
||||||
/* DDK got it wrong! */
|
* got it wrong! */
|
||||||
#ifdef NTSTATUS_FROM_WIN32
|
#ifdef NTSTATUS_FROM_WIN32
|
||||||
# undef NTSTATUS_FROM_WIN32
|
# undef NTSTATUS_FROM_WIN32
|
||||||
#endif
|
#endif
|
||||||
@@ -4109,6 +4109,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* from winternl.h */
|
/* from winternl.h */
|
||||||
|
#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32_)
|
||||||
|
#define __UNICODE_STRING_DEFINED
|
||||||
|
#endif
|
||||||
typedef struct _UNICODE_STRING {
|
typedef struct _UNICODE_STRING {
|
||||||
USHORT Length;
|
USHORT Length;
|
||||||
USHORT MaximumLength;
|
USHORT MaximumLength;
|
||||||
@@ -4524,6 +4527,9 @@ typedef VOID (NTAPI *PIO_APC_ROUTINE)
|
|||||||
PIO_STATUS_BLOCK IoStatusBlock,
|
PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
ULONG Reserved);
|
ULONG Reserved);
|
||||||
|
|
||||||
|
typedef NTSTATUS (NTAPI *sRtlGetVersion)
|
||||||
|
(PRTL_OSVERSIONINFOW lpVersionInformation);
|
||||||
|
|
||||||
typedef ULONG (NTAPI *sRtlNtStatusToDosError)
|
typedef ULONG (NTAPI *sRtlNtStatusToDosError)
|
||||||
(NTSTATUS Status);
|
(NTSTATUS Status);
|
||||||
|
|
||||||
@@ -4659,48 +4665,6 @@ typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
|
|||||||
DWORD dwMilliseconds,
|
DWORD dwMilliseconds,
|
||||||
BOOL fAlertable);
|
BOOL fAlertable);
|
||||||
|
|
||||||
typedef BOOL (WINAPI* sSetFileCompletionNotificationModes)
|
|
||||||
(HANDLE FileHandle,
|
|
||||||
UCHAR Flags);
|
|
||||||
|
|
||||||
typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW)
|
|
||||||
(LPCWSTR lpSymlinkFileName,
|
|
||||||
LPCWSTR lpTargetFileName,
|
|
||||||
DWORD dwFlags);
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI* sCancelIoEx)
|
|
||||||
(HANDLE hFile,
|
|
||||||
LPOVERLAPPED lpOverlapped);
|
|
||||||
|
|
||||||
typedef VOID (WINAPI* sInitializeConditionVariable)
|
|
||||||
(PCONDITION_VARIABLE ConditionVariable);
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI* sSleepConditionVariableCS)
|
|
||||||
(PCONDITION_VARIABLE ConditionVariable,
|
|
||||||
PCRITICAL_SECTION CriticalSection,
|
|
||||||
DWORD dwMilliseconds);
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI* sSleepConditionVariableSRW)
|
|
||||||
(PCONDITION_VARIABLE ConditionVariable,
|
|
||||||
PSRWLOCK SRWLock,
|
|
||||||
DWORD dwMilliseconds,
|
|
||||||
ULONG Flags);
|
|
||||||
|
|
||||||
typedef VOID (WINAPI* sWakeAllConditionVariable)
|
|
||||||
(PCONDITION_VARIABLE ConditionVariable);
|
|
||||||
|
|
||||||
typedef VOID (WINAPI* sWakeConditionVariable)
|
|
||||||
(PCONDITION_VARIABLE ConditionVariable);
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI* sCancelSynchronousIo)
|
|
||||||
(HANDLE hThread);
|
|
||||||
|
|
||||||
typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
|
|
||||||
(HANDLE hFile,
|
|
||||||
LPWSTR lpszFilePath,
|
|
||||||
DWORD cchFilePath,
|
|
||||||
DWORD dwFlags);
|
|
||||||
|
|
||||||
/* from powerbase.h */
|
/* from powerbase.h */
|
||||||
#ifndef DEVICE_NOTIFY_CALLBACK
|
#ifndef DEVICE_NOTIFY_CALLBACK
|
||||||
# define DEVICE_NOTIFY_CALLBACK 2
|
# define DEVICE_NOTIFY_CALLBACK 2
|
||||||
@@ -4755,6 +4719,7 @@ typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
|
|||||||
|
|
||||||
|
|
||||||
/* Ntdll function pointers */
|
/* Ntdll function pointers */
|
||||||
|
extern sRtlGetVersion pRtlGetVersion;
|
||||||
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||||
extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
|
extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
|
||||||
extern sNtQueryInformationFile pNtQueryInformationFile;
|
extern sNtQueryInformationFile pNtQueryInformationFile;
|
||||||
@@ -4763,20 +4728,8 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
|
|||||||
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
||||||
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
|
|
||||||
|
|
||||||
/* Kernel32 function pointers */
|
/* Kernel32 function pointers */
|
||||||
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||||
extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes;
|
|
||||||
extern sCreateSymbolicLinkW pCreateSymbolicLinkW;
|
|
||||||
extern sCancelIoEx pCancelIoEx;
|
|
||||||
extern sInitializeConditionVariable pInitializeConditionVariable;
|
|
||||||
extern sSleepConditionVariableCS pSleepConditionVariableCS;
|
|
||||||
extern sSleepConditionVariableSRW pSleepConditionVariableSRW;
|
|
||||||
extern sWakeAllConditionVariable pWakeAllConditionVariable;
|
|
||||||
extern sWakeConditionVariable pWakeConditionVariable;
|
|
||||||
extern sCancelSynchronousIo pCancelSynchronousIo;
|
|
||||||
extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
|
||||||
|
|
||||||
|
|
||||||
/* Powrprof.dll function pointer */
|
/* Powrprof.dll function pointer */
|
||||||
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||||
@@ -4784,19 +4737,4 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi
|
|||||||
/* User32.dll function pointer */
|
/* User32.dll function pointer */
|
||||||
extern sSetWinEventHook pSetWinEventHook;
|
extern sSetWinEventHook pSetWinEventHook;
|
||||||
|
|
||||||
/* iphlpapi.dll function pointer */
|
|
||||||
union _NET_LUID_LH;
|
|
||||||
typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)(
|
|
||||||
ULONG InterfaceIndex,
|
|
||||||
union _NET_LUID_LH *InterfaceLuid);
|
|
||||||
|
|
||||||
typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)(
|
|
||||||
const union _NET_LUID_LH *InterfaceLuid,
|
|
||||||
PWSTR InterfaceName,
|
|
||||||
size_t Length);
|
|
||||||
|
|
||||||
extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid;
|
|
||||||
extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* UV_WIN_WINAPI_H_ */
|
#endif /* UV_WIN_WINAPI_H_ */
|
||||||
|
|||||||
@@ -256,8 +256,8 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) {
|
|||||||
default:
|
default:
|
||||||
if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&
|
if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&
|
||||||
(status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {
|
(status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {
|
||||||
/* It's a windows error that has been previously mapped to an */
|
/* It's a windows error that has been previously mapped to an ntstatus
|
||||||
/* ntstatus code. */
|
* code. */
|
||||||
return (DWORD) (status & 0xffff);
|
return (DWORD) (status & 0xffff);
|
||||||
} else {
|
} else {
|
||||||
/* The default fallback for unmappable ntstatus codes. */
|
/* The default fallback for unmappable ntstatus codes. */
|
||||||
@@ -519,8 +519,8 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
|
|||||||
sizeof *info_out);
|
sizeof *info_out);
|
||||||
|
|
||||||
if (overlapped == NULL) {
|
if (overlapped == NULL) {
|
||||||
/* If this is a blocking operation, wait for the event to become */
|
/* If this is a blocking operation, wait for the event to become signaled,
|
||||||
/* signaled, and then grab the real status from the io status block. */
|
* and then grab the real status from the io status block. */
|
||||||
if (status == STATUS_PENDING) {
|
if (status == STATUS_PENDING) {
|
||||||
DWORD r = WaitForSingleObject(event, INFINITE);
|
DWORD r = WaitForSingleObject(event, INFINITE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user