mirror of
https://github.com/reactos/CMake.git
synced 2024-12-03 00:57:25 +00:00
Merge topic 'update-libuv'
6db7b352
libuv: Update build within CMakeb58d48c1
Merge branch 'upstream-libuv' into update-libuvf4a26c74
libuv 2018-01-19 (63de1eca)e8b57c22
libuv: Teach import script to add missing newlines Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1666
This commit is contained in:
commit
63f263b27f
@ -20,6 +20,8 @@ extract_source () {
|
||||
git_archive
|
||||
pushd "${extractdir}/${name}-reduced"
|
||||
echo "* -whitespace" > .gitattributes
|
||||
echo >> src/unix/aix-common.c
|
||||
echo >> src/unix/ibmi.c
|
||||
popd
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ set(uv_sources
|
||||
src/threadpool.c
|
||||
src/uv-common.c
|
||||
src/uv-common.h
|
||||
src/uv-data-getter-setters.c
|
||||
src/version.c
|
||||
)
|
||||
if(WIN32)
|
||||
@ -130,6 +131,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
||||
)
|
||||
list(APPEND uv_sources
|
||||
src/unix/aix.c
|
||||
src/unix/aix-common.c
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -170,7 +172,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
src/unix/fsevents.c
|
||||
src/unix/kqueue.c
|
||||
src/unix/proctitle.c
|
||||
src/unix/pthread-barrier.c
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -62,8 +62,8 @@ The externally maintained libraries used by libuv are:
|
||||
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
|
||||
clause BSD license.
|
||||
|
||||
- pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile
|
||||
Communications AB. Three clause BSD license.
|
||||
- pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
|
||||
Three clause BSD license.
|
||||
|
||||
- android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design
|
||||
Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement
|
||||
|
@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#endif
|
||||
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
|
||||
#define UV__PTHREAD_BARRIER_FALLBACK 1
|
||||
|
||||
/*
|
||||
* To maintain ABI compatibility with
|
||||
|
@ -416,4 +416,16 @@
|
||||
# define UV__EHOSTDOWN (-4031)
|
||||
#endif
|
||||
|
||||
#if defined(EREMOTEIO) && !defined(_WIN32)
|
||||
# define UV__EREMOTEIO (-EREMOTEIO)
|
||||
#else
|
||||
# define UV__EREMOTEIO (-4030)
|
||||
#endif
|
||||
|
||||
#if defined(ENOTTY) && !defined(_WIN32)
|
||||
# define UV__ENOTTY (-ENOTTY)
|
||||
#else
|
||||
# define UV__ENOTTY (-4029)
|
||||
#endif
|
||||
|
||||
#endif /* UV_ERRNO_H_ */
|
||||
|
@ -27,4 +27,7 @@
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
void* ep; \
|
||||
|
||||
#define UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
char rfis_rftok[8]; \
|
||||
|
||||
#endif /* UV_MVS_H */
|
||||
|
@ -50,6 +50,8 @@
|
||||
# include "uv-linux.h"
|
||||
#elif defined (__MVS__)
|
||||
# include "uv-os390.h"
|
||||
#elif defined(_PASE)
|
||||
# include "uv-posix.h"
|
||||
#elif defined(_AIX)
|
||||
# include "uv-aix.h"
|
||||
#elif defined(__sun)
|
||||
@ -125,6 +127,7 @@ typedef struct uv_buf_t {
|
||||
typedef int uv_file;
|
||||
typedef int uv_os_sock_t;
|
||||
typedef int uv_os_fd_t;
|
||||
typedef pid_t uv_pid_t;
|
||||
|
||||
#ifdef CMAKE_BOOTSTRAP
|
||||
#define UV_ONCE_INIT 0
|
||||
@ -379,4 +382,97 @@ typedef struct {
|
||||
uv_fs_event_cb cb; \
|
||||
UV_PLATFORM_FS_EVENT_FIELDS \
|
||||
|
||||
/* fs open() flags supported on this platform: */
|
||||
#if defined(O_APPEND)
|
||||
# define UV_FS_O_APPEND O_APPEND
|
||||
#else
|
||||
# define UV_FS_O_APPEND 0
|
||||
#endif
|
||||
#if defined(O_CREAT)
|
||||
# define UV_FS_O_CREAT O_CREAT
|
||||
#else
|
||||
# define UV_FS_O_CREAT 0
|
||||
#endif
|
||||
#if defined(O_DIRECT)
|
||||
# define UV_FS_O_DIRECT O_DIRECT
|
||||
#else
|
||||
# define UV_FS_O_DIRECT 0
|
||||
#endif
|
||||
#if defined(O_DIRECTORY)
|
||||
# define UV_FS_O_DIRECTORY O_DIRECTORY
|
||||
#else
|
||||
# define UV_FS_O_DIRECTORY 0
|
||||
#endif
|
||||
#if defined(O_DSYNC)
|
||||
# define UV_FS_O_DSYNC O_DSYNC
|
||||
#else
|
||||
# define UV_FS_O_DSYNC 0
|
||||
#endif
|
||||
#if defined(O_EXCL)
|
||||
# define UV_FS_O_EXCL O_EXCL
|
||||
#else
|
||||
# define UV_FS_O_EXCL 0
|
||||
#endif
|
||||
#if defined(O_EXLOCK)
|
||||
# define UV_FS_O_EXLOCK O_EXLOCK
|
||||
#else
|
||||
# define UV_FS_O_EXLOCK 0
|
||||
#endif
|
||||
#if defined(O_NOATIME)
|
||||
# define UV_FS_O_NOATIME O_NOATIME
|
||||
#else
|
||||
# define UV_FS_O_NOATIME 0
|
||||
#endif
|
||||
#if defined(O_NOCTTY)
|
||||
# define UV_FS_O_NOCTTY O_NOCTTY
|
||||
#else
|
||||
# define UV_FS_O_NOCTTY 0
|
||||
#endif
|
||||
#if defined(O_NOFOLLOW)
|
||||
# define UV_FS_O_NOFOLLOW O_NOFOLLOW
|
||||
#else
|
||||
# define UV_FS_O_NOFOLLOW 0
|
||||
#endif
|
||||
#if defined(O_NONBLOCK)
|
||||
# define UV_FS_O_NONBLOCK O_NONBLOCK
|
||||
#else
|
||||
# define UV_FS_O_NONBLOCK 0
|
||||
#endif
|
||||
#if defined(O_RDONLY)
|
||||
# define UV_FS_O_RDONLY O_RDONLY
|
||||
#else
|
||||
# define UV_FS_O_RDONLY 0
|
||||
#endif
|
||||
#if defined(O_RDWR)
|
||||
# define UV_FS_O_RDWR O_RDWR
|
||||
#else
|
||||
# define UV_FS_O_RDWR 0
|
||||
#endif
|
||||
#if defined(O_SYMLINK)
|
||||
# define UV_FS_O_SYMLINK O_SYMLINK
|
||||
#else
|
||||
# define UV_FS_O_SYMLINK 0
|
||||
#endif
|
||||
#if defined(O_SYNC)
|
||||
# define UV_FS_O_SYNC O_SYNC
|
||||
#else
|
||||
# define UV_FS_O_SYNC 0
|
||||
#endif
|
||||
#if defined(O_TRUNC)
|
||||
# define UV_FS_O_TRUNC O_TRUNC
|
||||
#else
|
||||
# define UV_FS_O_TRUNC 0
|
||||
#endif
|
||||
#if defined(O_WRONLY)
|
||||
# define UV_FS_O_WRONLY O_WRONLY
|
||||
#else
|
||||
# define UV_FS_O_WRONLY 0
|
||||
#endif
|
||||
|
||||
/* fs open() flags supported on other platforms: */
|
||||
#define UV_FS_O_RANDOM 0
|
||||
#define UV_FS_O_SHORT_LIVED 0
|
||||
#define UV_FS_O_SEQUENTIAL 0
|
||||
#define UV_FS_O_TEMPORARY 0
|
||||
|
||||
#endif /* UV_UNIX_H */
|
||||
|
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 11
|
||||
#define UV_VERSION_MINOR 19
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_IS_RELEASE 0
|
||||
#define UV_VERSION_SUFFIX "dev"
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0502
|
||||
# define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
|
||||
@ -233,6 +233,7 @@ typedef struct uv_buf_t {
|
||||
typedef int uv_file;
|
||||
typedef SOCKET uv_os_sock_t;
|
||||
typedef HANDLE uv_os_fd_t;
|
||||
typedef int uv_pid_t;
|
||||
|
||||
typedef HANDLE uv_thread_t;
|
||||
|
||||
@ -659,3 +660,28 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
||||
#ifndef X_OK
|
||||
#define X_OK 1
|
||||
#endif
|
||||
|
||||
/* fs open() flags supported on this platform: */
|
||||
#define UV_FS_O_APPEND _O_APPEND
|
||||
#define UV_FS_O_CREAT _O_CREAT
|
||||
#define UV_FS_O_EXCL _O_EXCL
|
||||
#define UV_FS_O_RANDOM _O_RANDOM
|
||||
#define UV_FS_O_RDONLY _O_RDONLY
|
||||
#define UV_FS_O_RDWR _O_RDWR
|
||||
#define UV_FS_O_SEQUENTIAL _O_SEQUENTIAL
|
||||
#define UV_FS_O_SHORT_LIVED _O_SHORT_LIVED
|
||||
#define UV_FS_O_TEMPORARY _O_TEMPORARY
|
||||
#define UV_FS_O_TRUNC _O_TRUNC
|
||||
#define UV_FS_O_WRONLY _O_WRONLY
|
||||
|
||||
/* fs open() flags supported on other platforms (or mapped on this platform): */
|
||||
#define UV_FS_O_DIRECT 0x02000000 /* FILE_FLAG_NO_BUFFERING */
|
||||
#define UV_FS_O_DIRECTORY 0
|
||||
#define UV_FS_O_DSYNC 0x04000000 /* FILE_FLAG_WRITE_THROUGH */
|
||||
#define UV_FS_O_EXLOCK 0x10000000 /* EXCLUSIVE SHARING MODE */
|
||||
#define UV_FS_O_NOATIME 0
|
||||
#define UV_FS_O_NOCTTY 0
|
||||
#define UV_FS_O_NOFOLLOW 0
|
||||
#define UV_FS_O_NONBLOCK 0
|
||||
#define UV_FS_O_SYMLINK 0
|
||||
#define UV_FS_O_SYNC 0x08000000 /* FILE_FLAG_WRITE_THROUGH */
|
||||
|
@ -144,6 +144,8 @@ extern "C" {
|
||||
XX(ENXIO, "no such device or address") \
|
||||
XX(EMLINK, "too many links") \
|
||||
XX(EHOSTDOWN, "host is down") \
|
||||
XX(EREMOTEIO, "remote I/O error") \
|
||||
XX(ENOTTY, "inappropriate ioctl for device") \
|
||||
|
||||
#define UV_HANDLE_TYPE_MAP(XX) \
|
||||
XX(ASYNC, async) \
|
||||
@ -427,7 +429,17 @@ struct uv_handle_s {
|
||||
};
|
||||
|
||||
UV_EXTERN size_t uv_handle_size(uv_handle_type type);
|
||||
UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
|
||||
UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);
|
||||
UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);
|
||||
UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
|
||||
UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);
|
||||
|
||||
UV_EXTERN size_t uv_req_size(uv_req_type type);
|
||||
UV_EXTERN void* uv_req_get_data(const uv_req_t* req);
|
||||
UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);
|
||||
UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);
|
||||
UV_EXTERN const char* uv_req_type_name(uv_req_type type);
|
||||
|
||||
UV_EXTERN int uv_is_active(const uv_handle_t* handle);
|
||||
|
||||
@ -467,6 +479,8 @@ struct uv_stream_s {
|
||||
UV_STREAM_FIELDS
|
||||
};
|
||||
|
||||
UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);
|
||||
|
||||
UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
|
||||
UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
|
||||
|
||||
@ -644,6 +658,8 @@ UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
|
||||
uv_alloc_cb alloc_cb,
|
||||
uv_udp_recv_cb recv_cb);
|
||||
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
|
||||
UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
|
||||
UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
|
||||
|
||||
|
||||
/*
|
||||
@ -712,6 +728,7 @@ UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,
|
||||
UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
|
||||
UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
|
||||
UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
|
||||
UV_EXTERN int uv_pipe_chmod(uv_pipe_t* handle, int flags);
|
||||
|
||||
|
||||
struct uv_poll_s {
|
||||
@ -723,7 +740,8 @@ struct uv_poll_s {
|
||||
enum uv_poll_event {
|
||||
UV_READABLE = 1,
|
||||
UV_WRITABLE = 2,
|
||||
UV_DISCONNECT = 4
|
||||
UV_DISCONNECT = 4,
|
||||
UV_PRIORITIZED = 8
|
||||
};
|
||||
|
||||
UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
|
||||
@ -962,6 +980,7 @@ UV_EXTERN int uv_spawn(uv_loop_t* loop,
|
||||
const uv_process_options_t* options);
|
||||
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
|
||||
UV_EXTERN int uv_kill(int pid, int signum);
|
||||
UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);
|
||||
|
||||
|
||||
/*
|
||||
@ -1038,6 +1057,7 @@ UV_EXTERN int uv_get_process_title(char* buffer, size_t size);
|
||||
UV_EXTERN int uv_set_process_title(const char* title);
|
||||
UV_EXTERN int uv_resident_set_memory(size_t* rss);
|
||||
UV_EXTERN int uv_uptime(double* uptime);
|
||||
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
|
||||
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
@ -1069,6 +1089,8 @@ UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
|
||||
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_getppid(void);
|
||||
|
||||
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);
|
||||
@ -1115,7 +1137,8 @@ typedef enum {
|
||||
UV_FS_READLINK,
|
||||
UV_FS_CHOWN,
|
||||
UV_FS_FCHOWN,
|
||||
UV_FS_REALPATH
|
||||
UV_FS_REALPATH,
|
||||
UV_FS_COPYFILE
|
||||
} uv_fs_type;
|
||||
|
||||
/* uv_fs_t is a subclass of uv_req_t. */
|
||||
@ -1131,6 +1154,12 @@ struct uv_fs_s {
|
||||
UV_FS_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
|
||||
UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
|
||||
UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
|
||||
UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
|
||||
UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
|
||||
|
||||
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
|
||||
UV_EXTERN int uv_fs_close(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
@ -1160,6 +1189,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop,
|
||||
unsigned int nbufs,
|
||||
int64_t offset,
|
||||
uv_fs_cb cb);
|
||||
/*
|
||||
* This flag can be used with uv_fs_copyfile() to return an error if the
|
||||
* destination already exists.
|
||||
*/
|
||||
#define UV_FS_COPYFILE_EXCL 0x0001
|
||||
|
||||
UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
const char* new_path,
|
||||
int flags,
|
||||
uv_fs_cb cb);
|
||||
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
@ -1393,6 +1434,21 @@ UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size
|
||||
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
|
||||
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
|
||||
|
||||
#if defined(IF_NAMESIZE)
|
||||
# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
|
||||
#elif defined(IFNAMSIZ)
|
||||
# define UV_IF_NAMESIZE (IFNAMSIZ + 1)
|
||||
#else
|
||||
# define UV_IF_NAMESIZE (16 + 1)
|
||||
#endif
|
||||
|
||||
UV_EXTERN int uv_if_indextoname(unsigned int ifindex,
|
||||
char* buffer,
|
||||
size_t* size);
|
||||
UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,
|
||||
char* buffer,
|
||||
size_t* size);
|
||||
|
||||
UV_EXTERN int uv_exepath(char* buffer, size_t* size);
|
||||
|
||||
UV_EXTERN int uv_cwd(char* buffer, size_t* size);
|
||||
@ -1412,6 +1468,7 @@ UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);
|
||||
UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);
|
||||
|
||||
UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
|
||||
UV_EXTERN int uv_mutex_init_recursive(uv_mutex_t* handle);
|
||||
UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
|
||||
UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
|
||||
UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
|
||||
@ -1484,6 +1541,8 @@ struct uv_loop_s {
|
||||
UV_LOOP_PRIVATE_FIELDS
|
||||
};
|
||||
|
||||
UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
|
||||
UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
|
||||
|
||||
/* Don't export the private CPP symbols. */
|
||||
#undef UV_HANDLE_TYPE_PRIVATE
|
||||
|
@ -38,7 +38,6 @@ static uv_thread_t* threads;
|
||||
static uv_thread_t default_threads[4];
|
||||
static QUEUE exit_message;
|
||||
static QUEUE wq;
|
||||
static volatile int initialized;
|
||||
|
||||
|
||||
static void uv__cancelled(struct uv__work* w) {
|
||||
@ -53,7 +52,8 @@ static void worker(void* arg) {
|
||||
struct uv__work* w;
|
||||
QUEUE* q;
|
||||
|
||||
(void) arg;
|
||||
uv_sem_post((uv_sem_t*) arg);
|
||||
arg = NULL;
|
||||
|
||||
for (;;) {
|
||||
uv_mutex_lock(&mutex);
|
||||
@ -105,7 +105,7 @@ static void post(QUEUE* q) {
|
||||
UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
unsigned int i;
|
||||
|
||||
if (initialized == 0)
|
||||
if (nthreads == 0)
|
||||
return;
|
||||
|
||||
post(&exit_message);
|
||||
@ -122,7 +122,6 @@ UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
|
||||
threads = NULL;
|
||||
nthreads = 0;
|
||||
initialized = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -130,6 +129,7 @@ UV_DESTRUCTOR(static void cleanup(void)) {
|
||||
static void init_threads(void) {
|
||||
unsigned int i;
|
||||
const char* val;
|
||||
uv_sem_t sem;
|
||||
|
||||
nthreads = ARRAY_SIZE(default_threads);
|
||||
val = getenv("UV_THREADPOOL_SIZE");
|
||||
@ -157,11 +157,17 @@ static void init_threads(void) {
|
||||
|
||||
QUEUE_INIT(&wq);
|
||||
|
||||
if (uv_sem_init(&sem, 0))
|
||||
abort();
|
||||
|
||||
for (i = 0; i < nthreads; i++)
|
||||
if (uv_thread_create(threads + i, worker, NULL))
|
||||
if (uv_thread_create(threads + i, worker, &sem))
|
||||
abort();
|
||||
|
||||
initialized = 1;
|
||||
for (i = 0; i < nthreads; i++)
|
||||
uv_sem_wait(&sem);
|
||||
|
||||
uv_sem_destroy(&sem);
|
||||
}
|
||||
|
||||
|
||||
|
292
Utilities/cmlibuv/src/unix/aix-common.c
Normal file
292
Utilities/cmlibuv/src/unix/aix-common.c
Normal file
@ -0,0 +1,292 @@
|
||||
/* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <utmp.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <sys/protosw.h>
|
||||
#include <procinfo.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <sys/pollset.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/mntctl.h>
|
||||
#include <sys/vmount.h>
|
||||
#include <limits.h>
|
||||
#include <strings.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
uint64_t G = 1000000000;
|
||||
timebasestruct_t t;
|
||||
read_wall_time(&t, TIMEBASE_SZ);
|
||||
time_base_to_time(&t, TIMEBASE_SZ);
|
||||
return (uint64_t) t.tb_high * G + t.tb_low;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We could use a static buffer for the path manipulations that we need outside
|
||||
* of the function, but this function could be called by multiple consumers and
|
||||
* we don't want to potentially create a race condition in the use of snprintf.
|
||||
* There is no direct way of getting the exe path in AIX - either through /procfs
|
||||
* or through some libc APIs. The below approach is to parse the argv[0]'s pattern
|
||||
* and use it in conjunction with PATH environment variable to craft one.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int res;
|
||||
char args[PATH_MAX];
|
||||
char abspath[PATH_MAX];
|
||||
size_t abspath_size;
|
||||
struct procsinfo pi;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
pi.pi_pid = getpid();
|
||||
res = getargs(&pi, sizeof(pi), args, sizeof(args));
|
||||
if (res < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Possibilities for args:
|
||||
* i) an absolute path such as: /home/user/myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
||||
* iii) a bare filename such as "node", after exporting PATH variable
|
||||
* to its location.
|
||||
*/
|
||||
|
||||
/* Case i) and ii) absolute or relative paths */
|
||||
if (strchr(args, '/') != NULL) {
|
||||
if (realpath(args, abspath) != abspath)
|
||||
return -errno;
|
||||
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
/* Case iii). Search PATH environment variable */
|
||||
char trypath[PATH_MAX];
|
||||
char *clonedpath = NULL;
|
||||
char *token = NULL;
|
||||
char *path = getenv("PATH");
|
||||
|
||||
if (path == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
clonedpath = uv__strdup(path);
|
||||
if (clonedpath == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
token = strtok(clonedpath, ":");
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
/* Check the match is executable */
|
||||
if (access(abspath, X_OK) == 0) {
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
uv__free(clonedpath);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
uv__free(clonedpath);
|
||||
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
uv__free(cpu_infos[i].model);
|
||||
}
|
||||
|
||||
uv__free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
uv_interface_address_t* address;
|
||||
int sockfd, inet6, size = 1;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr, *p, flg;
|
||||
struct sockaddr_dl* sa_addr;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
|
||||
ifc.ifc_len = size;
|
||||
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
||||
|
||||
/* Count all up and running ipv4/ipv6 addresses */
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
ifr = (struct ifreq*)
|
||||
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
||||
|
||||
if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
||||
p->ifr_addr.sa_family == AF_INET))
|
||||
continue;
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
uv__close(sockfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
address = *addresses;
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
ifr = (struct ifreq*)
|
||||
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
||||
|
||||
if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
||||
p->ifr_addr.sa_family == AF_INET))
|
||||
continue;
|
||||
|
||||
inet6 = (p->ifr_addr.sa_family == AF_INET6);
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->ifr_name);
|
||||
|
||||
if (inet6)
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||
else
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
|
||||
sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
|
||||
memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (inet6)
|
||||
address->netmask.netmask6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||
else
|
||||
address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
|
||||
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
||||
|
||||
address++;
|
||||
}
|
||||
|
||||
#undef ADDR_SIZE
|
||||
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
uv__free(addresses[i].name);
|
||||
}
|
||||
|
||||
uv__free(addresses);
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
/* 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
|
||||
@ -64,11 +65,18 @@
|
||||
#define RDWR_BUF_SIZE 4096
|
||||
#define EQ(a,b) (strcmp(a,b) == 0)
|
||||
|
||||
static uv_mutex_t process_title_mutex;
|
||||
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
||||
static void* args_mem = NULL;
|
||||
static char** process_argv = NULL;
|
||||
static int process_argc = 0;
|
||||
static char* process_title_ptr = NULL;
|
||||
|
||||
static void init_process_title_mutex_once(void) {
|
||||
uv_mutex_init(&process_title_mutex);
|
||||
}
|
||||
|
||||
|
||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
loop->fs_fd = -1;
|
||||
|
||||
@ -316,104 +324,6 @@ update_timeout:
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
uint64_t G = 1000000000;
|
||||
timebasestruct_t t;
|
||||
read_wall_time(&t, TIMEBASE_SZ);
|
||||
time_base_to_time(&t, TIMEBASE_SZ);
|
||||
return (uint64_t) t.tb_high * G + t.tb_low;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We could use a static buffer for the path manipulations that we need outside
|
||||
* of the function, but this function could be called by multiple consumers and
|
||||
* we don't want to potentially create a race condition in the use of snprintf.
|
||||
* There is no direct way of getting the exe path in AIX - either through /procfs
|
||||
* or through some libc APIs. The below approach is to parse the argv[0]'s pattern
|
||||
* and use it in conjunction with PATH environment variable to craft one.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int res;
|
||||
char args[PATH_MAX];
|
||||
char abspath[PATH_MAX];
|
||||
size_t abspath_size;
|
||||
struct procsinfo pi;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
pi.pi_pid = getpid();
|
||||
res = getargs(&pi, sizeof(pi), args, sizeof(args));
|
||||
if (res < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Possibilities for args:
|
||||
* i) an absolute path such as: /home/user/myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
||||
* iii) a bare filename such as "node", after exporting PATH variable
|
||||
* to its location.
|
||||
*/
|
||||
|
||||
/* Case i) and ii) absolute or relative paths */
|
||||
if (strchr(args, '/') != NULL) {
|
||||
if (realpath(args, abspath) != abspath)
|
||||
return -errno;
|
||||
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
/* Case iii). Search PATH environment variable */
|
||||
char trypath[PATH_MAX];
|
||||
char *clonedpath = NULL;
|
||||
char *token = NULL;
|
||||
char *path = getenv("PATH");
|
||||
|
||||
if (path == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
clonedpath = uv__strdup(path);
|
||||
if (clonedpath == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
token = strtok(clonedpath, ":");
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
/* Check the match is executable */
|
||||
if (access(abspath, X_OK) == 0) {
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
uv__free(clonedpath);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
uv__free(clonedpath);
|
||||
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
perfstat_memory_total_t mem_total;
|
||||
int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
|
||||
@ -855,6 +765,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
||||
uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
|
||||
handle->path = uv__strdup(filename);
|
||||
handle->cb = cb;
|
||||
handle->dir_filename = NULL;
|
||||
|
||||
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
|
||||
|
||||
@ -952,6 +863,9 @@ int uv_set_process_title(const char* title) {
|
||||
if (new_title == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
|
||||
/* If this is the first time this is set,
|
||||
* don't free and set argv[1] to NULL.
|
||||
*/
|
||||
@ -964,6 +878,8 @@ int uv_set_process_title(const char* title) {
|
||||
if (process_argc > 1)
|
||||
process_argv[1] = NULL;
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -976,8 +892,13 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
else if (size <= len)
|
||||
return -ENOBUFS;
|
||||
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
|
||||
memcpy(buffer, process_argv[0], len + 1);
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1017,6 +938,7 @@ int uv_uptime(double* uptime) {
|
||||
size_t entries = 0;
|
||||
time_t boot_time;
|
||||
|
||||
boot_time = 0;
|
||||
utmpname(UTMP_FILE);
|
||||
|
||||
setutent();
|
||||
@ -1093,130 +1015,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
uv__free(cpu_infos[i].model);
|
||||
}
|
||||
|
||||
uv__free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
uv_interface_address_t* address;
|
||||
int sockfd, size = 1;
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr, *p, flg;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
|
||||
ifc.ifc_len = size;
|
||||
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
||||
|
||||
/* Count all up and running ipv4/ipv6 addresses */
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
ifr = (struct ifreq*)
|
||||
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
||||
|
||||
if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
||||
p->ifr_addr.sa_family == AF_INET))
|
||||
continue;
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = (uv_interface_address_t*)
|
||||
uv__malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
uv__close(sockfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
address = *addresses;
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
ifr = (struct ifreq*)
|
||||
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
||||
|
||||
if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
||||
p->ifr_addr.sa_family == AF_INET))
|
||||
continue;
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->ifr_name);
|
||||
|
||||
if (p->ifr_addr.sa_family == AF_INET6) {
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||
} else {
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
}
|
||||
|
||||
/* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
|
||||
|
||||
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
||||
|
||||
address++;
|
||||
}
|
||||
|
||||
#undef ADDR_SIZE
|
||||
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
uv__free(addresses[i].name);
|
||||
}
|
||||
|
||||
uv__free(addresses);
|
||||
}
|
||||
|
||||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
||||
struct pollfd* events;
|
||||
uintptr_t i;
|
||||
|
@ -43,9 +43,10 @@ typedef struct NetlinkList
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(void)
|
||||
static int netlink_socket(pid_t *p_pid)
|
||||
{
|
||||
struct sockaddr_nl l_addr;
|
||||
socklen_t l_len;
|
||||
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if(l_socket < 0)
|
||||
@ -61,6 +62,14 @@ static int netlink_socket(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_len = sizeof(l_addr);
|
||||
if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
*p_pid = l_addr.nl_pid;
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
@ -128,7 +137,7 @@ static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
|
||||
{
|
||||
size_t l_size = 4096;
|
||||
void *l_buffer = NULL;
|
||||
@ -153,11 +162,10 @@ static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_don
|
||||
}
|
||||
if(l_read >= 0)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -207,7 +215,7 @@ static void freeResultList(NetlinkList *p_list)
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *getResultList(int p_socket, int p_request)
|
||||
static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid)
|
||||
{
|
||||
int l_size;
|
||||
int l_done;
|
||||
@ -227,7 +235,7 @@ static NetlinkList *getResultList(int p_socket, int p_request)
|
||||
{
|
||||
NetlinkList *l_item;
|
||||
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done);
|
||||
/* Error */
|
||||
if(!l_hdr)
|
||||
{
|
||||
@ -449,7 +457,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
|
||||
char *l_name;
|
||||
char *l_addr;
|
||||
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if(l_info->ifa_family == AF_PACKET)
|
||||
@ -471,7 +479,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -496,7 +504,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
|
||||
}
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
@ -559,7 +567,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
|
||||
{
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
char l_mask[16] = {0};
|
||||
unsigned char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for(i=0; i<(l_prefix/8); ++i)
|
||||
{
|
||||
@ -578,18 +586,17 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
|
||||
static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
|
||||
{
|
||||
|
||||
int l_numLinks = 0;
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -612,16 +619,15 @@ static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifadd
|
||||
return l_numLinks;
|
||||
}
|
||||
|
||||
static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -648,6 +654,7 @@ int getifaddrs(struct ifaddrs **ifap)
|
||||
int l_socket;
|
||||
int l_result;
|
||||
int l_numLinks;
|
||||
pid_t l_pid;
|
||||
NetlinkList *l_linkResults;
|
||||
NetlinkList *l_addrResults;
|
||||
|
||||
@ -657,20 +664,20 @@ int getifaddrs(struct ifaddrs **ifap)
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
l_socket = netlink_socket();
|
||||
l_socket = netlink_socket(&l_pid);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_linkResults = getResultList(l_socket, RTM_GETLINK);
|
||||
l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid);
|
||||
if(!l_linkResults)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l_addrResults = getResultList(l_socket, RTM_GETADDR);
|
||||
l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid);
|
||||
if(!l_addrResults)
|
||||
{
|
||||
close(l_socket);
|
||||
@ -679,8 +686,8 @@ int getifaddrs(struct ifaddrs **ifap)
|
||||
}
|
||||
|
||||
l_result = 0;
|
||||
l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
|
||||
if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
|
||||
l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap);
|
||||
if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1)
|
||||
{
|
||||
l_result = -1;
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
#include <atomic.h>
|
||||
#define __sync_val_compare_and_swap(p, o, n) atomic_cas_ptr(p, o, n)
|
||||
#endif
|
||||
|
||||
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
|
||||
@ -49,6 +48,8 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
return oldval;
|
||||
else
|
||||
return op4;
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
return atomic_cas_uint(ptr, oldval, newval);
|
||||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
@ -83,6 +84,8 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
|
||||
return oldval;
|
||||
else
|
||||
return op4;
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
return atomic_cas_ulong(ptr, oldval, newval);
|
||||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
|
@ -31,11 +31,20 @@
|
||||
#include <net/if_dl.h>
|
||||
#endif
|
||||
|
||||
static int uv__ifaddr_exclude(struct ifaddrs *ent) {
|
||||
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
|
||||
return 1;
|
||||
if (ent->ifa_addr == NULL)
|
||||
return 1;
|
||||
#if !defined(__CYGWIN__) && !defined(__MSYS__)
|
||||
/*
|
||||
* If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family`
|
||||
* equals to `AF_LINK` or not. Otherwise, the result depends on the operation
|
||||
* system with `AF_LINK` or `PF_INET`.
|
||||
*/
|
||||
if (exclude_type == UV__EXCLUDE_IFPHYS)
|
||||
return (ent->ifa_addr->sa_family != AF_LINK);
|
||||
#endif
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
/*
|
||||
* On BSD getifaddrs returns information related to the raw underlying
|
||||
@ -43,7 +52,11 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) {
|
||||
*/
|
||||
if (ent->ifa_addr->sa_family == AF_LINK)
|
||||
return 1;
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#elif defined(__NetBSD__)
|
||||
if (ent->ifa_addr->sa_family != PF_INET &&
|
||||
ent->ifa_addr->sa_family != PF_INET6)
|
||||
return 1;
|
||||
#elif defined(__OpenBSD__)
|
||||
if (ent->ifa_addr->sa_family != PF_INET)
|
||||
return 1;
|
||||
#endif
|
||||
@ -63,7 +76,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
|
||||
/* Count the number of interfaces */
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent))
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||
continue;
|
||||
(*count)++;
|
||||
}
|
||||
@ -78,7 +91,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
address = *addresses;
|
||||
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent))
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||
continue;
|
||||
|
||||
address->name = uv__strdup(ent->ifa_name);
|
||||
@ -102,7 +115,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
|
||||
/* Fill in physical addresses for each interface */
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent))
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
|
||||
continue;
|
||||
|
||||
address = *addresses;
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@ -59,13 +58,19 @@
|
||||
|
||||
#if defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__)
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__)
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/filio.h>
|
||||
# include <sys/wait.h>
|
||||
# define UV__O_CLOEXEC O_CLOEXEC
|
||||
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
|
||||
# define uv__accept4 accept4
|
||||
# endif
|
||||
# if defined(__NetBSD__)
|
||||
# define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
|
||||
# endif
|
||||
# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
|
||||
# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
|
||||
# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
|
||||
# endif
|
||||
@ -82,6 +87,10 @@
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__MVS__)
|
||||
#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
|
||||
#endif
|
||||
|
||||
/* Fallback for the maximum hostname length */
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
# define MAXHOSTNAMELEN 256
|
||||
@ -459,7 +468,9 @@ int uv__accept(int sockfd) {
|
||||
assert(sockfd >= 0);
|
||||
|
||||
while (1) {
|
||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10)
|
||||
#if defined(__linux__) || \
|
||||
(defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
|
||||
defined(__NetBSD__)
|
||||
static int no_accept4;
|
||||
|
||||
if (no_accept4)
|
||||
@ -835,7 +846,7 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
|
||||
|
||||
|
||||
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
|
||||
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
|
||||
assert(0 != events);
|
||||
assert(w->fd >= 0);
|
||||
assert(w->fd < INT_MAX);
|
||||
@ -863,7 +874,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
|
||||
|
||||
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
|
||||
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
|
||||
assert(0 != events);
|
||||
|
||||
if (w->fd == -1)
|
||||
@ -895,7 +906,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
|
||||
|
||||
void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
|
||||
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP);
|
||||
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
QUEUE_REMOVE(&w->pending_queue);
|
||||
|
||||
/* Remove stale events for this file descriptor */
|
||||
@ -910,7 +921,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
|
||||
|
||||
|
||||
int uv__io_active(const uv__io_t* w, unsigned int events) {
|
||||
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
|
||||
assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
|
||||
assert(0 != events);
|
||||
return 0 != (w->pevents & events);
|
||||
}
|
||||
@ -985,7 +996,7 @@ int uv__open_cloexec(const char* path, int flags) {
|
||||
|
||||
int uv__dup2_cloexec(int oldfd, int newfd) {
|
||||
int r;
|
||||
#if defined(__FreeBSD__) && __FreeBSD__ >= 10
|
||||
#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
|
||||
r = dup3(oldfd, newfd, O_CLOEXEC);
|
||||
if (r == -1)
|
||||
return -errno;
|
||||
@ -1289,6 +1300,9 @@ int uv_os_setenv(const char* name, const char* value) {
|
||||
|
||||
|
||||
int uv_os_unsetenv(const char* name) {
|
||||
if (name == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (unsetenv(name) != 0)
|
||||
return -errno;
|
||||
|
||||
@ -1324,3 +1338,18 @@ int uv_os_gethostname(char* buffer, size_t* size) {
|
||||
*size = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uv_os_fd_t uv_get_osfhandle(int fd) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
uv_pid_t uv_os_getpid(void) {
|
||||
return getpid();
|
||||
}
|
||||
|
||||
|
||||
uv_pid_t uv_os_getppid(void) {
|
||||
return getppid();
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <kvm.h>
|
||||
#include <paths.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/types.h>
|
||||
@ -48,9 +47,16 @@
|
||||
# define CP_INTR 4
|
||||
#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) {
|
||||
return uv__kqueue_init(loop);
|
||||
}
|
||||
@ -161,9 +167,20 @@ char** uv_setup_args(int argc, char** 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 -ENOMEM;
|
||||
}
|
||||
|
||||
uv__free(process_title);
|
||||
process_title = uv__strdup(title);
|
||||
process_title = new_title;
|
||||
|
||||
oid[0] = CTL_KERN;
|
||||
oid[1] = KERN_PROC;
|
||||
@ -177,6 +194,8 @@ int uv_set_process_title(const char* title) {
|
||||
process_title,
|
||||
strlen(process_title) + 1);
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -187,51 +206,54 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0)
|
||||
return -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)
|
||||
if (size < len) {
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
return -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) {
|
||||
kvm_t *kd = NULL;
|
||||
struct kinfo_proc *kinfo = NULL;
|
||||
pid_t pid;
|
||||
int nprocs;
|
||||
size_t page_size = getpagesize();
|
||||
struct kinfo_proc kinfo;
|
||||
size_t page_size;
|
||||
size_t kinfo_size;
|
||||
int mib[4];
|
||||
|
||||
pid = getpid();
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = getpid();
|
||||
|
||||
kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
|
||||
if (kd == NULL) goto error;
|
||||
kinfo_size = sizeof(kinfo);
|
||||
|
||||
kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs);
|
||||
if (kinfo == NULL) goto error;
|
||||
if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
|
||||
return -errno;
|
||||
|
||||
page_size = getpagesize();
|
||||
|
||||
#ifdef __DragonFly__
|
||||
*rss = kinfo->kp_vm_rssize * page_size;
|
||||
*rss = kinfo.kp_vm_rssize * page_size;
|
||||
#else
|
||||
*rss = kinfo->ki_rssize * page_size;
|
||||
*rss = kinfo.ki_rssize * page_size;
|
||||
#endif
|
||||
|
||||
kvm_close(kd);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (kd) kvm_close(kd);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
|
||||
@ -254,6 +276,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uv_cpu_info_t* cpu_info;
|
||||
const char* maxcpus_key;
|
||||
const char* cptimes_key;
|
||||
const char* model_key;
|
||||
char model[512];
|
||||
long* cp_times;
|
||||
int numcpus;
|
||||
@ -272,8 +295,20 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
cptimes_key = "kern.cp_times";
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
/* The key hw.model and hw.clockrate are not available on FreeBSD ARM. */
|
||||
model_key = "hw.machine";
|
||||
cpuspeed = 0;
|
||||
#else
|
||||
model_key = "hw.model";
|
||||
|
||||
size = sizeof(cpuspeed);
|
||||
if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0))
|
||||
return -errno;
|
||||
#endif
|
||||
|
||||
size = sizeof(model);
|
||||
if (sysctlbyname("hw.model", &model, &size, NULL, 0))
|
||||
if (sysctlbyname(model_key, &model, &size, NULL, 0))
|
||||
return -errno;
|
||||
|
||||
size = sizeof(numcpus);
|
||||
@ -286,12 +321,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
|
||||
*count = numcpus;
|
||||
|
||||
size = sizeof(cpuspeed);
|
||||
if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) {
|
||||
uv__free(*cpu_infos);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of
|
||||
* ncpu.
|
||||
*/
|
||||
|
@ -60,8 +60,14 @@
|
||||
# include <sys/sendfile.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# include <copyfile.h>
|
||||
#endif
|
||||
|
||||
#define INIT(subtype) \
|
||||
do { \
|
||||
if (req == NULL) \
|
||||
return -EINVAL; \
|
||||
req->type = UV_FS; \
|
||||
if (cb != NULL) \
|
||||
uv__req_init(loop, req, UV_FS); \
|
||||
@ -126,26 +132,33 @@
|
||||
while (0)
|
||||
|
||||
|
||||
static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
||||
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
|
||||
return fdatasync(req->file);
|
||||
#elif defined(__APPLE__)
|
||||
static ssize_t uv__fs_fsync(uv_fs_t* req) {
|
||||
#if defined(__APPLE__)
|
||||
/* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
|
||||
* to the drive platters. This is in contrast to Linux's fdatasync and fsync
|
||||
* which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
|
||||
* for flushing buffered data to permanent storage.
|
||||
* for flushing buffered data to permanent storage. If F_FULLFSYNC is not
|
||||
* supported by the file system we should fall back to fsync(). This is the
|
||||
* same approach taken by sqlite.
|
||||
*/
|
||||
return fcntl(req->file, F_FULLFSYNC);
|
||||
int r;
|
||||
|
||||
r = fcntl(req->file, F_FULLFSYNC);
|
||||
if (r != 0 && errno == ENOTTY)
|
||||
r = fsync(req->file);
|
||||
return r;
|
||||
#else
|
||||
return fsync(req->file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_fsync(uv_fs_t* req) {
|
||||
#if defined(__APPLE__)
|
||||
/* See the comment in uv__fs_fdatasync. */
|
||||
return fcntl(req->file, F_FULLFSYNC);
|
||||
static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
||||
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
|
||||
return fdatasync(req->file);
|
||||
#elif defined(__APPLE__)
|
||||
/* See the comment in uv__fs_fsync. */
|
||||
return uv__fs_fsync(req);
|
||||
#else
|
||||
return fsync(req->file);
|
||||
#endif
|
||||
@ -442,7 +455,12 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__MVS__)
|
||||
len = os390_readlink(req->path, buf, len);
|
||||
#else
|
||||
len = readlink(req->path, buf, len);
|
||||
#endif
|
||||
|
||||
|
||||
if (len == -1) {
|
||||
uv__free(buf);
|
||||
@ -776,6 +794,118 @@ done:
|
||||
return r;
|
||||
}
|
||||
|
||||
static ssize_t uv__fs_copyfile(uv_fs_t* req) {
|
||||
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
||||
/* On macOS, use the native copyfile(3). */
|
||||
copyfile_flags_t flags;
|
||||
|
||||
flags = COPYFILE_ALL;
|
||||
|
||||
if (req->flags & UV_FS_COPYFILE_EXCL)
|
||||
flags |= COPYFILE_EXCL;
|
||||
|
||||
return copyfile(req->path, req->new_path, NULL, flags);
|
||||
#else
|
||||
uv_fs_t fs_req;
|
||||
uv_file srcfd;
|
||||
uv_file dstfd;
|
||||
struct stat statsbuf;
|
||||
int dst_flags;
|
||||
int result;
|
||||
int err;
|
||||
size_t bytes_to_send;
|
||||
int64_t in_offset;
|
||||
|
||||
dstfd = -1;
|
||||
err = 0;
|
||||
|
||||
/* Open the source file. */
|
||||
srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
if (srcfd < 0)
|
||||
return srcfd;
|
||||
|
||||
/* Get the source file's mode. */
|
||||
if (fstat(srcfd, &statsbuf)) {
|
||||
err = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
|
||||
if (req->flags & UV_FS_COPYFILE_EXCL)
|
||||
dst_flags |= O_EXCL;
|
||||
|
||||
/* Open the destination file. */
|
||||
dstfd = uv_fs_open(NULL,
|
||||
&fs_req,
|
||||
req->new_path,
|
||||
dst_flags,
|
||||
statsbuf.st_mode,
|
||||
NULL);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
|
||||
if (dstfd < 0) {
|
||||
err = dstfd;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fchmod(dstfd, statsbuf.st_mode) == -1) {
|
||||
err = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bytes_to_send = statsbuf.st_size;
|
||||
in_offset = 0;
|
||||
while (bytes_to_send != 0) {
|
||||
err = uv_fs_sendfile(NULL,
|
||||
&fs_req,
|
||||
dstfd,
|
||||
srcfd,
|
||||
in_offset,
|
||||
bytes_to_send,
|
||||
NULL);
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
if (err < 0)
|
||||
break;
|
||||
bytes_to_send -= fs_req.result;
|
||||
in_offset += fs_req.result;
|
||||
}
|
||||
|
||||
out:
|
||||
if (err < 0)
|
||||
result = err;
|
||||
else
|
||||
result = 0;
|
||||
|
||||
/* Close the source file. */
|
||||
err = uv__close_nocheckstdio(srcfd);
|
||||
|
||||
/* Don't overwrite any existing errors. */
|
||||
if (err != 0 && result == 0)
|
||||
result = err;
|
||||
|
||||
/* Close the destination file if it is open. */
|
||||
if (dstfd >= 0) {
|
||||
err = uv__close_nocheckstdio(dstfd);
|
||||
|
||||
/* Don't overwrite any existing errors. */
|
||||
if (err != 0 && result == 0)
|
||||
result = err;
|
||||
|
||||
/* Remove the destination file if something went wrong. */
|
||||
if (result != 0) {
|
||||
uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
|
||||
/* Ignore the unlink return value, as an error already happened. */
|
||||
uv_fs_req_cleanup(&fs_req);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
|
||||
dst->st_dev = src->st_dev;
|
||||
dst->st_mode = src->st_mode;
|
||||
@ -956,6 +1086,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
X(CHMOD, chmod(req->path, req->mode));
|
||||
X(CHOWN, chown(req->path, req->uid, req->gid));
|
||||
X(CLOSE, close(req->file));
|
||||
X(COPYFILE, uv__fs_copyfile(req));
|
||||
X(FCHMOD, fchmod(req->file, req->mode));
|
||||
X(FCHOWN, fchown(req->file, req->uid, req->gid));
|
||||
X(FDATASYNC, uv__fs_fdatasync(req));
|
||||
@ -1196,10 +1327,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
|
||||
unsigned int nbufs,
|
||||
int64_t off,
|
||||
uv_fs_cb cb) {
|
||||
INIT(READ);
|
||||
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
INIT(READ);
|
||||
req->file = file;
|
||||
|
||||
req->nbufs = nbufs;
|
||||
@ -1334,10 +1466,11 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
unsigned int nbufs,
|
||||
int64_t off,
|
||||
uv_fs_cb cb) {
|
||||
INIT(WRITE);
|
||||
|
||||
if (bufs == NULL || nbufs == 0)
|
||||
return -EINVAL;
|
||||
|
||||
INIT(WRITE);
|
||||
req->file = file;
|
||||
|
||||
req->nbufs = nbufs;
|
||||
@ -1359,6 +1492,9 @@ int uv_fs_write(uv_loop_t* loop,
|
||||
|
||||
|
||||
void uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
if (req == NULL)
|
||||
return;
|
||||
|
||||
/* Only necessary for asychronous requests, i.e., requests with a callback.
|
||||
* Synchronous ones don't copy their arguments and have req->path and
|
||||
* req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the
|
||||
@ -1377,3 +1513,20 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
|
||||
uv__free(req->ptr);
|
||||
req->ptr = NULL;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_copyfile(uv_loop_t* loop,
|
||||
uv_fs_t* req,
|
||||
const char* path,
|
||||
const char* new_path,
|
||||
int flags,
|
||||
uv_fs_cb cb) {
|
||||
INIT(COPYFILE);
|
||||
|
||||
if (flags & ~UV_FS_COPYFILE_EXCL)
|
||||
return -EINVAL;
|
||||
|
||||
PATH2;
|
||||
req->flags = flags;
|
||||
POST;
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
||||
uv_loop_t* loop;
|
||||
uv__cf_loop_state_t* state;
|
||||
uv__fsevents_event_t* event;
|
||||
FSEventStreamEventFlags flags;
|
||||
QUEUE head;
|
||||
|
||||
loop = info;
|
||||
@ -245,8 +246,10 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
||||
|
||||
/* Process and filter out events */
|
||||
for (i = 0; i < numEvents; i++) {
|
||||
flags = eventFlags[i];
|
||||
|
||||
/* Ignore system events */
|
||||
if (eventFlags[i] & kFSEventsSystem)
|
||||
if (flags & kFSEventsSystem)
|
||||
continue;
|
||||
|
||||
path = paths[i];
|
||||
@ -271,6 +274,9 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
||||
/* 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) */
|
||||
@ -291,12 +297,24 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
|
||||
|
||||
memset(event, 0, sizeof(*event));
|
||||
memcpy(event->path, path, len + 1);
|
||||
event->events = UV_RENAME;
|
||||
|
||||
if ((eventFlags[i] & kFSEventsModified) != 0 &&
|
||||
(eventFlags[i] & kFSEventsRenamed) == 0)
|
||||
#ifdef MAC_OS_X_VERSION_10_7
|
||||
if (0 != (flags & kFSEventsModified) &&
|
||||
0 == (flags & kFSEventsRenamed)) {
|
||||
event->events = UV_CHANGE;
|
||||
else
|
||||
event->events = UV_RENAME;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <net/if.h> /* if_indextoname() */
|
||||
|
||||
/* EAI_* constants. */
|
||||
#include <netdb.h>
|
||||
@ -200,3 +201,32 @@ void uv_freeaddrinfo(struct addrinfo* ai) {
|
||||
if (ai)
|
||||
freeaddrinfo(ai);
|
||||
}
|
||||
|
||||
|
||||
int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
|
||||
char ifname_buf[UV_IF_NAMESIZE];
|
||||
size_t len;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (if_indextoname(ifindex, ifname_buf) == NULL)
|
||||
return -errno;
|
||||
|
||||
len = strnlen(ifname_buf, sizeof(ifname_buf));
|
||||
|
||||
if (*size <= len) {
|
||||
*size = len + 1;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
memcpy(buffer, ifname_buf, len);
|
||||
buffer[len] = '\0';
|
||||
*size = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
|
||||
return uv_if_indextoname(ifindex, buffer, size);
|
||||
}
|
||||
|
112
Utilities/cmlibuv/src/unix/ibmi.c
Normal file
112
Utilities/cmlibuv/src/unix/ibmi.c
Normal file
@ -0,0 +1,112 @@
|
||||
/* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <utmp.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <sys/protosw.h>
|
||||
#include <procinfo.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/mntctl.h>
|
||||
#include <sys/vmount.h>
|
||||
#include <limits.h>
|
||||
#include <strings.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_total_memory(void) {
|
||||
return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
|
||||
}
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
avg[0] = avg[1] = avg[2] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int uv_resident_set_memory(size_t* rss) {
|
||||
return UV_ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
int uv_uptime(double* uptime) {
|
||||
return UV_ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
unsigned int numcpus, idx = 0;
|
||||
uv_cpu_info_t* cpu_info;
|
||||
|
||||
*cpu_infos = NULL;
|
||||
*count = 0;
|
||||
|
||||
numcpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
*cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t));
|
||||
if (!*cpu_infos) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cpu_info = *cpu_infos;
|
||||
for (idx = 0; idx < numcpus; idx++) {
|
||||
cpu_info->speed = 0;
|
||||
cpu_info->model = uv__strdup("unknown");
|
||||
cpu_info->cpu_times.user = 0;
|
||||
cpu_info->cpu_times.sys = 0;
|
||||
cpu_info->cpu_times.idle = 0;
|
||||
cpu_info->cpu_times.irq = 0;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
cpu_info++;
|
||||
}
|
||||
*count = numcpus;
|
||||
|
||||
return 0;
|
||||
}
|
@ -120,6 +120,12 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
|
||||
# define UV__POLLRDHUP 0x2000
|
||||
#endif
|
||||
|
||||
#ifdef POLLPRI
|
||||
# define UV__POLLPRI POLLPRI
|
||||
#else
|
||||
# define UV__POLLPRI 0
|
||||
#endif
|
||||
|
||||
#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
|
||||
/*
|
||||
* It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
|
||||
@ -155,6 +161,12 @@ enum {
|
||||
UV_LOOP_BLOCK_SIGPROF = 1
|
||||
};
|
||||
|
||||
/* flags of excluding ifaddr */
|
||||
enum {
|
||||
UV__EXCLUDE_IFPHYS,
|
||||
UV__EXCLUDE_IFADDR
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
UV_CLOCK_PRECISE = 0, /* Use the highest resolution clock available. */
|
||||
UV_CLOCK_FAST = 1 /* Use the fastest clock with <= 1ms granularity. */
|
||||
@ -173,7 +185,8 @@ struct uv__stream_queued_fds_s {
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__linux__) || \
|
||||
defined(__OpenBSD__)
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
#define uv__cloexec uv__cloexec_ioctl
|
||||
#define uv__nonblock uv__nonblock_ioctl
|
||||
#else
|
||||
|
@ -34,6 +34,17 @@
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
* Required on
|
||||
* - Until at least FreeBSD 11.0
|
||||
* - Older versions of Mac OS X
|
||||
*
|
||||
* http://www.boost.org/doc/libs/1_61_0/boost/asio/detail/kqueue_reactor.hpp
|
||||
*/
|
||||
#ifndef EV_OOBAND
|
||||
#define EV_OOBAND EV_FLAG1
|
||||
#endif
|
||||
|
||||
static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
|
||||
|
||||
|
||||
@ -48,11 +59,12 @@ int uv__kqueue_init(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
|
||||
#if defined(__APPLE__)
|
||||
static int uv__has_forked_with_cfrunloop;
|
||||
#endif
|
||||
|
||||
int uv__io_fork(uv_loop_t* loop) {
|
||||
int err;
|
||||
uv__close(loop->backend_fd);
|
||||
loop->backend_fd = -1;
|
||||
err = uv__kqueue_init(loop);
|
||||
if (err)
|
||||
@ -166,6 +178,16 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((w->events & UV__POLLPRI) == 0 && (w->pevents & UV__POLLPRI) != 0) {
|
||||
EV_SET(events + nevents, w->fd, EV_OOBAND, EV_ADD, 0, 0, 0);
|
||||
|
||||
if (++nevents == ARRAY_SIZE(events)) {
|
||||
if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
|
||||
abort();
|
||||
nevents = 0;
|
||||
}
|
||||
}
|
||||
|
||||
w->events = w->pevents;
|
||||
}
|
||||
|
||||
@ -275,6 +297,20 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->filter == EV_OOBAND) {
|
||||
if (w->pevents & UV__POLLPRI) {
|
||||
revents |= UV__POLLPRI;
|
||||
w->rcount = ev->data;
|
||||
} else {
|
||||
/* TODO batch up */
|
||||
struct kevent events[1];
|
||||
EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
|
||||
if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
|
||||
if (errno != ENOENT)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
if (ev->filter == EVFILT_WRITE) {
|
||||
if (w->pevents & POLLOUT) {
|
||||
revents |= POLLOUT;
|
||||
|
@ -388,7 +388,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
* free when we switch over to edge-triggered I/O.
|
||||
*/
|
||||
if (pe->events == POLLERR || pe->events == POLLHUP)
|
||||
pe->events |= w->pevents & (POLLIN | POLLOUT);
|
||||
pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI);
|
||||
|
||||
if (pe->events != 0) {
|
||||
/* Run signal watchers last. This also affects child process watchers
|
||||
@ -837,7 +837,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
uv__free(cpu_infos);
|
||||
}
|
||||
|
||||
static int uv__ifaddr_exclude(struct ifaddrs *ent) {
|
||||
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
||||
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
|
||||
return 1;
|
||||
if (ent->ifa_addr == NULL)
|
||||
@ -847,8 +847,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) {
|
||||
* devices. We're not interested in this information yet.
|
||||
*/
|
||||
if (ent->ifa_addr->sa_family == PF_PACKET)
|
||||
return 1;
|
||||
return 0;
|
||||
return exclude_type;
|
||||
return !exclude_type;
|
||||
}
|
||||
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
@ -869,7 +869,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
|
||||
/* Count the number of interfaces */
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent))
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||
continue;
|
||||
|
||||
(*count)++;
|
||||
@ -887,7 +887,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
address = *addresses;
|
||||
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent))
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||
continue;
|
||||
|
||||
address->name = uv__strdup(ent->ifa_name);
|
||||
@ -911,7 +911,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
|
||||
|
||||
/* Fill in physical addresses for each interface */
|
||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||
if (uv__ifaddr_exclude(ent))
|
||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
|
||||
continue;
|
||||
|
||||
address = *addresses;
|
||||
|
@ -31,7 +31,6 @@ int uv_loop_init(uv_loop_t* loop) {
|
||||
void* saved_data;
|
||||
int err;
|
||||
|
||||
uv__signal_global_once_init();
|
||||
|
||||
saved_data = loop->data;
|
||||
memset(loop, 0, sizeof(*loop));
|
||||
@ -68,6 +67,7 @@ int uv_loop_init(uv_loop_t* loop) {
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
uv__signal_global_once_init();
|
||||
err = uv_signal_init(loop, &loop->child_watcher);
|
||||
if (err)
|
||||
goto fail_signal_init;
|
||||
|
@ -40,9 +40,16 @@
|
||||
#include <unistd.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) {
|
||||
return uv__kqueue_init(loop);
|
||||
}
|
||||
@ -66,22 +73,32 @@ void uv_loadavg(double avg[3]) {
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
/* Intermediate buffer, retrieving partial path name does not work
|
||||
* As of NetBSD-8(beta), vnode->path translator does not handle files
|
||||
* with longer names than 31 characters.
|
||||
*/
|
||||
char int_buf[PATH_MAX];
|
||||
size_t int_size;
|
||||
int mib[4];
|
||||
size_t cb;
|
||||
pid_t mypid;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
mypid = getpid();
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC_ARGS;
|
||||
mib[2] = mypid;
|
||||
mib[3] = KERN_PROC_ARGV;
|
||||
mib[2] = -1;
|
||||
mib[3] = KERN_PROC_PATHNAME;
|
||||
int_size = ARRAY_SIZE(int_buf);
|
||||
|
||||
cb = *size;
|
||||
if (sysctl(mib, 4, buffer, &cb, NULL, 0))
|
||||
if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
|
||||
return -errno;
|
||||
|
||||
/* Copy string from the intermediate buffer to outer one with appropriate
|
||||
* length.
|
||||
*/
|
||||
strlcpy(buffer, int_buf, *size);
|
||||
|
||||
/* Set new size. */
|
||||
*size = strlen(buffer);
|
||||
|
||||
return 0;
|
||||
@ -124,11 +141,24 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
|
||||
|
||||
int uv_set_process_title(const char* title) {
|
||||
if (process_title) uv__free(process_title);
|
||||
char* new_title;
|
||||
|
||||
process_title = uv__strdup(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 -ENOMEM;
|
||||
}
|
||||
|
||||
uv__free(process_title);
|
||||
process_title = new_title;
|
||||
setproctitle("%s", title);
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -139,17 +169,24 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0)
|
||||
return -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)
|
||||
if (size < len) {
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
memcpy(buffer, process_title, len);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
buffer[len] = '\0';
|
||||
|
||||
return 0;
|
||||
|
@ -36,9 +36,16 @@
|
||||
#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) {
|
||||
return uv__kqueue_init(loop);
|
||||
}
|
||||
@ -146,9 +153,24 @@ char** uv_setup_args(int argc, char** 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 -ENOMEM;
|
||||
}
|
||||
|
||||
uv__free(process_title);
|
||||
process_title = uv__strdup(title);
|
||||
process_title = new_title;
|
||||
setproctitle("%s", title);
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -159,17 +181,24 @@ int uv_get_process_title(char* buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0)
|
||||
return -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)
|
||||
if (size < len) {
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
memcpy(buffer, process_title, len);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
buffer[len] = '\0';
|
||||
|
||||
return 0;
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <search.h>
|
||||
#include <termios.h>
|
||||
#include <sys/msg.h>
|
||||
|
||||
#define CW_CONDVAR 32
|
||||
|
||||
@ -103,10 +105,19 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
|
||||
unsigned int newsize;
|
||||
unsigned int i;
|
||||
struct pollfd* newlst;
|
||||
struct pollfd event;
|
||||
|
||||
if (len <= lst->size)
|
||||
return;
|
||||
|
||||
if (lst->size == 0)
|
||||
event.fd = -1;
|
||||
else {
|
||||
/* Extract the message queue at the end. */
|
||||
event = lst->items[lst->size - 1];
|
||||
lst->items[lst->size - 1].fd = -1;
|
||||
}
|
||||
|
||||
newsize = next_power_of_two(len);
|
||||
newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0]));
|
||||
|
||||
@ -115,32 +126,101 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
|
||||
for (i = lst->size; i < newsize; ++i)
|
||||
newlst[i].fd = -1;
|
||||
|
||||
/* Restore the message queue at the end */
|
||||
newlst[newsize - 1] = event;
|
||||
|
||||
lst->items = newlst;
|
||||
lst->size = newsize;
|
||||
}
|
||||
|
||||
|
||||
static void init_message_queue(uv__os390_epoll* lst) {
|
||||
struct {
|
||||
long int header;
|
||||
char body;
|
||||
} msg;
|
||||
|
||||
/* initialize message queue */
|
||||
lst->msg_queue = msgget(IPC_PRIVATE, 0622 | IPC_CREAT);
|
||||
if (lst->msg_queue == -1)
|
||||
abort();
|
||||
|
||||
/*
|
||||
On z/OS, the message queue will be affiliated with the process only
|
||||
when a send is performed on it. Once this is done, the system
|
||||
can be queried for all message queues belonging to our process id.
|
||||
*/
|
||||
msg.header = 1;
|
||||
if (msgsnd(lst->msg_queue, &msg, sizeof(msg.body), 0) != 0)
|
||||
abort();
|
||||
|
||||
/* Clean up the dummy message sent above */
|
||||
if (msgrcv(lst->msg_queue, &msg, sizeof(msg.body), 0, 0) != sizeof(msg.body))
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
static void before_fork(void) {
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
}
|
||||
|
||||
|
||||
static void after_fork(void) {
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
}
|
||||
|
||||
|
||||
static void child_fork(void) {
|
||||
QUEUE* q;
|
||||
uv_once_t child_once = UV_ONCE_INIT;
|
||||
|
||||
/* reset once */
|
||||
memcpy(&once, &child_once, sizeof(child_once));
|
||||
|
||||
/* reset epoll list */
|
||||
while (!QUEUE_EMPTY(&global_epoll_queue)) {
|
||||
uv__os390_epoll* lst;
|
||||
q = QUEUE_HEAD(&global_epoll_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
lst = QUEUE_DATA(q, uv__os390_epoll, member);
|
||||
uv__free(lst->items);
|
||||
lst->items = NULL;
|
||||
lst->size = 0;
|
||||
}
|
||||
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
uv_mutex_destroy(&global_epoll_lock);
|
||||
}
|
||||
|
||||
|
||||
static void epoll_init(void) {
|
||||
QUEUE_INIT(&global_epoll_queue);
|
||||
if (uv_mutex_init(&global_epoll_lock))
|
||||
abort();
|
||||
|
||||
if (pthread_atfork(&before_fork, &after_fork, &child_fork))
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
uv__os390_epoll* epoll_create1(int flags) {
|
||||
uv__os390_epoll* lst;
|
||||
|
||||
uv_once(&once, epoll_init);
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
lst = uv__malloc(sizeof(*lst));
|
||||
if (lst == -1)
|
||||
return NULL;
|
||||
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
if (lst != NULL) {
|
||||
/* initialize list */
|
||||
lst->size = 0;
|
||||
lst->items = NULL;
|
||||
init_message_queue(lst);
|
||||
maybe_resize(lst, 1);
|
||||
lst->items[lst->size - 1].fd = lst->msg_queue;
|
||||
lst->items[lst->size - 1].events = POLLIN;
|
||||
uv_once(&once, epoll_init);
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
}
|
||||
|
||||
/* initialize list */
|
||||
lst->size = 0;
|
||||
lst->items = NULL;
|
||||
return lst;
|
||||
}
|
||||
|
||||
@ -149,22 +229,32 @@ int epoll_ctl(uv__os390_epoll* lst,
|
||||
int op,
|
||||
int fd,
|
||||
struct epoll_event *event) {
|
||||
if(op == EPOLL_CTL_DEL) {
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
|
||||
if (op == EPOLL_CTL_DEL) {
|
||||
if (fd >= lst->size || lst->items[fd].fd == -1) {
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
lst->items[fd].fd = -1;
|
||||
} else if(op == EPOLL_CTL_ADD) {
|
||||
maybe_resize(lst, fd + 1);
|
||||
} else if (op == EPOLL_CTL_ADD) {
|
||||
|
||||
/* Resizing to 'fd + 1' would expand the list to contain at least
|
||||
* 'fd'. But we need to guarantee that the last index on the list
|
||||
* is reserved for the message queue. So specify 'fd + 2' instead.
|
||||
*/
|
||||
maybe_resize(lst, fd + 2);
|
||||
if (lst->items[fd].fd != -1) {
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
lst->items[fd].fd = fd;
|
||||
lst->items[fd].events = event->events;
|
||||
} else if(op == EPOLL_CTL_MOD) {
|
||||
} else if (op == EPOLL_CTL_MOD) {
|
||||
if (fd >= lst->size || lst->items[fd].fd == -1) {
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
@ -172,44 +262,36 @@ int epoll_ctl(uv__os390_epoll* lst,
|
||||
} else
|
||||
abort();
|
||||
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
||||
int maxevents, int timeout) {
|
||||
size_t size;
|
||||
nmsgsfds_t size;
|
||||
struct pollfd* pfds;
|
||||
int pollret;
|
||||
int reventcount;
|
||||
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
size = lst->size;
|
||||
size = _SET_FDS_MSGS(size, 1, lst->size - 1);
|
||||
pfds = lst->items;
|
||||
pollret = poll(pfds, size, timeout);
|
||||
if(pollret == -1)
|
||||
if (pollret <= 0)
|
||||
return pollret;
|
||||
|
||||
pollret = _NFDS(pollret) + _NMSGS(pollret);
|
||||
|
||||
reventcount = 0;
|
||||
for (int i = 0; i < lst->size && i < maxevents; ++i) {
|
||||
for (int i = 0;
|
||||
i < lst->size && i < maxevents && reventcount < pollret; ++i) {
|
||||
struct epoll_event ev;
|
||||
|
||||
ev.events = 0;
|
||||
ev.fd = pfds[i].fd;
|
||||
if(!pfds[i].revents)
|
||||
if (pfds[i].fd == -1 || pfds[i].revents == 0)
|
||||
continue;
|
||||
|
||||
if(pfds[i].revents & POLLRDNORM)
|
||||
ev.events = ev.events | POLLIN;
|
||||
|
||||
if(pfds[i].revents & POLLWRNORM)
|
||||
ev.events = ev.events | POLLOUT;
|
||||
|
||||
if(pfds[i].revents & POLLHUP)
|
||||
ev.events = ev.events | POLLHUP;
|
||||
|
||||
pfds[i].revents = 0;
|
||||
ev.fd = pfds[i].fd;
|
||||
ev.events = pfds[i].revents;
|
||||
events[reventcount++] = ev;
|
||||
}
|
||||
|
||||
@ -235,9 +317,14 @@ int epoll_file_close(int fd) {
|
||||
}
|
||||
|
||||
void epoll_queue_close(uv__os390_epoll* lst) {
|
||||
/* Remove epoll instance from global queue */
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
QUEUE_REMOVE(&lst->member);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
|
||||
/* Free resources */
|
||||
msgctl(lst->msg_queue, IPC_RMID, NULL);
|
||||
lst->msg_queue = -1;
|
||||
uv__free(lst->items);
|
||||
lst->items = NULL;
|
||||
}
|
||||
@ -332,3 +419,81 @@ char* mkdtemp(char* path) {
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
ssize_t os390_readlink(const char* path, char* buf, size_t len) {
|
||||
ssize_t rlen;
|
||||
ssize_t vlen;
|
||||
ssize_t plen;
|
||||
char* delimiter;
|
||||
char old_delim;
|
||||
char* tmpbuf;
|
||||
char realpathstr[PATH_MAX + 1];
|
||||
|
||||
tmpbuf = uv__malloc(len + 1);
|
||||
if (tmpbuf == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rlen = readlink(path, tmpbuf, len);
|
||||
if (rlen < 0) {
|
||||
uv__free(tmpbuf);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
if (rlen < 3 || strncmp("/$", tmpbuf, 2) != 0) {
|
||||
/* Straightforward readlink. */
|
||||
memcpy(buf, tmpbuf, rlen);
|
||||
uv__free(tmpbuf);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* There is a parmlib variable at the beginning
|
||||
* which needs interpretation.
|
||||
*/
|
||||
tmpbuf[rlen] = '\0';
|
||||
delimiter = strchr(tmpbuf + 2, '/');
|
||||
if (delimiter == NULL)
|
||||
/* No slash at the end */
|
||||
delimiter = strchr(tmpbuf + 2, '\0');
|
||||
|
||||
/* Read real path of the variable. */
|
||||
old_delim = *delimiter;
|
||||
*delimiter = '\0';
|
||||
if (realpath(tmpbuf, realpathstr) == NULL) {
|
||||
uv__free(tmpbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* realpathstr is not guaranteed to end with null byte.*/
|
||||
realpathstr[PATH_MAX] = '\0';
|
||||
|
||||
/* Reset the delimiter and fill up the buffer. */
|
||||
*delimiter = old_delim;
|
||||
plen = strlen(delimiter);
|
||||
vlen = strlen(realpathstr);
|
||||
rlen = plen + vlen;
|
||||
if (rlen > len) {
|
||||
uv__free(tmpbuf);
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf, realpathstr, vlen);
|
||||
memcpy(buf + vlen, delimiter, plen);
|
||||
|
||||
/* Done using temporary buffer. */
|
||||
uv__free(tmpbuf);
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
|
||||
size_t strnlen(const char* str, size_t maxlen) {
|
||||
void* p = memchr(str, 0, maxlen);
|
||||
if (p == NULL)
|
||||
return maxlen;
|
||||
else
|
||||
return p - str;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ typedef struct {
|
||||
QUEUE member;
|
||||
struct pollfd* items;
|
||||
unsigned long size;
|
||||
int msg_queue;
|
||||
} uv__os390_epoll;
|
||||
|
||||
/* epoll api */
|
||||
@ -65,5 +66,7 @@ int scandir(const char* maindir, struct dirent*** namelist,
|
||||
int (*compar)(const struct dirent **,
|
||||
const struct dirent **));
|
||||
char *mkdtemp(char* path);
|
||||
ssize_t os390_readlink(const char* path, char* buf, size_t len);
|
||||
size_t strnlen(const char* str, size_t maxlen);
|
||||
|
||||
#endif /* UV_OS390_SYSCALL_H_ */
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include <utmpx.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ps.h>
|
||||
#include <builtins.h>
|
||||
#include <termios.h>
|
||||
#include <sys/msg.h>
|
||||
#if defined(__clang__)
|
||||
#include "csrsic.h"
|
||||
#else
|
||||
@ -32,6 +35,7 @@
|
||||
#endif
|
||||
|
||||
#define CVT_PTR 0x10
|
||||
#define PSA_PTR 0x00
|
||||
#define CSD_OFFSET 0x294
|
||||
|
||||
/*
|
||||
@ -69,6 +73,18 @@
|
||||
/* CPC model length from the CSRSI Service. */
|
||||
#define CPCMODEL_LENGTH 16
|
||||
|
||||
/* Pointer to the home (current) ASCB. */
|
||||
#define PSAAOLD 0x224
|
||||
|
||||
/* Pointer to rsm address space block extension. */
|
||||
#define ASCBRSME 0x16C
|
||||
|
||||
/*
|
||||
NUMBER OF FRAMES CURRENTLY IN USE BY THIS ADDRESS SPACE.
|
||||
It does not include 2G frames.
|
||||
*/
|
||||
#define RAXFMCT 0x2C
|
||||
|
||||
/* Thread Entry constants */
|
||||
#define PGTH_CURRENT 1
|
||||
#define PGTH_LEN 26
|
||||
@ -76,6 +92,9 @@
|
||||
#pragma linkage(BPX4GTH, OS)
|
||||
#pragma linkage(BPX1GTH, OS)
|
||||
|
||||
/* TOD Clock resolution in nanoseconds */
|
||||
#define TOD_RES 4.096
|
||||
|
||||
typedef unsigned data_area_ptr_assign_type;
|
||||
|
||||
typedef union {
|
||||
@ -100,7 +119,7 @@ void uv_loadavg(double avg[3]) {
|
||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
uv__os390_epoll* ep;
|
||||
|
||||
ep = epoll_create1(UV__EPOLL_CLOEXEC);
|
||||
ep = epoll_create1(0);
|
||||
loop->ep = ep;
|
||||
if (ep == NULL)
|
||||
return -errno;
|
||||
@ -118,9 +137,10 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
|
||||
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
struct timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3;
|
||||
unsigned long long timestamp;
|
||||
__stckf(×tamp);
|
||||
/* Convert to nanoseconds */
|
||||
return timestamp / TOD_RES;
|
||||
}
|
||||
|
||||
|
||||
@ -337,13 +357,17 @@ uint64_t uv_get_total_memory(void) {
|
||||
|
||||
|
||||
int uv_resident_set_memory(size_t* rss) {
|
||||
W_PSPROC buf;
|
||||
char* psa;
|
||||
char* ascb;
|
||||
char* rax;
|
||||
size_t nframes;
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1)
|
||||
return -EINVAL;
|
||||
psa = PSA_PTR;
|
||||
ascb = *(char* __ptr32 *)(psa + PSAAOLD);
|
||||
rax = *(char* __ptr32 *)(ascb + ASCBRSME);
|
||||
nframes = *(unsigned int*)(rax + RAXFMCT);
|
||||
|
||||
*rss = buf.ps_size;
|
||||
*rss = nframes * sysconf(_SC_PAGESIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -364,7 +388,6 @@ int uv_uptime(double* uptime) {
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uv_cpu_info_t* cpu_info;
|
||||
int result;
|
||||
int idx;
|
||||
siv1v2 info;
|
||||
data_area_ptr cvt = {0};
|
||||
@ -663,11 +686,124 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
uv_fs_event_stop(handle);
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
|
||||
const char* filename, unsigned int flags) {
|
||||
uv__os390_epoll* ep;
|
||||
_RFIS reg_struct;
|
||||
char* path;
|
||||
int rc;
|
||||
|
||||
if (uv__is_active(handle))
|
||||
return -EINVAL;
|
||||
|
||||
ep = handle->loop->ep;
|
||||
assert(ep->msg_queue != -1);
|
||||
|
||||
reg_struct.__rfis_cmd = _RFIS_REG;
|
||||
reg_struct.__rfis_qid = ep->msg_queue;
|
||||
reg_struct.__rfis_type = 1;
|
||||
memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle));
|
||||
|
||||
path = uv__strdup(filename);
|
||||
if (path == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct);
|
||||
if (rc != 0)
|
||||
return -errno;
|
||||
|
||||
uv__handle_start(handle);
|
||||
handle->path = path;
|
||||
handle->cb = cb;
|
||||
memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok,
|
||||
sizeof(handle->rfis_rftok));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
uv__os390_epoll* ep;
|
||||
_RFIS reg_struct;
|
||||
int rc;
|
||||
|
||||
if (!uv__is_active(handle))
|
||||
return 0;
|
||||
|
||||
ep = handle->loop->ep;
|
||||
assert(ep->msg_queue != -1);
|
||||
|
||||
reg_struct.__rfis_cmd = _RFIS_UNREG;
|
||||
reg_struct.__rfis_qid = ep->msg_queue;
|
||||
reg_struct.__rfis_type = 1;
|
||||
memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok,
|
||||
sizeof(handle->rfis_rftok));
|
||||
|
||||
/*
|
||||
* This call will take "/" as the path argument in case we
|
||||
* don't care to supply the correct path. The system will simply
|
||||
* ignore it.
|
||||
*/
|
||||
rc = __w_pioctl("/", _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct);
|
||||
if (rc != 0 && errno != EALREADY && errno != ENOENT)
|
||||
abort();
|
||||
|
||||
uv__handle_stop(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int os390_message_queue_handler(uv__os390_epoll* ep) {
|
||||
uv_fs_event_t* handle;
|
||||
int msglen;
|
||||
int events;
|
||||
_RFIM msg;
|
||||
|
||||
if (ep->msg_queue == -1)
|
||||
return 0;
|
||||
|
||||
msglen = msgrcv(ep->msg_queue, &msg, sizeof(msg), 0, IPC_NOWAIT);
|
||||
|
||||
if (msglen == -1 && errno == ENOMSG)
|
||||
return 0;
|
||||
|
||||
if (msglen == -1)
|
||||
abort();
|
||||
|
||||
events = 0;
|
||||
if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE)
|
||||
events = UV_CHANGE;
|
||||
else if (msg.__rfim_event == _RFIM_RENAME)
|
||||
events = UV_RENAME;
|
||||
else
|
||||
/* Some event that we are not interested in. */
|
||||
return 0;
|
||||
|
||||
handle = *(uv_fs_event_t**)(msg.__rfim_utok);
|
||||
handle->cb(handle, uv__basename_r(handle->path), events, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
static const int max_safe_timeout = 1789569;
|
||||
struct epoll_event events[1024];
|
||||
struct epoll_event* pe;
|
||||
struct epoll_event e;
|
||||
uv__os390_epoll* ep;
|
||||
int real_timeout;
|
||||
QUEUE* q;
|
||||
uv__io_t* w;
|
||||
@ -745,9 +881,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
SAVE_ERRNO(uv__update_time(loop));
|
||||
if (nfds == 0) {
|
||||
assert(timeout != -1);
|
||||
timeout = real_timeout - timeout;
|
||||
if (timeout > 0)
|
||||
|
||||
if (timeout > 0) {
|
||||
timeout = real_timeout - timeout;
|
||||
continue;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -779,6 +917,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
if (fd == -1)
|
||||
continue;
|
||||
|
||||
ep = loop->ep;
|
||||
if (fd == ep->msg_queue) {
|
||||
os390_message_queue_handler(ep);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(fd >= 0);
|
||||
assert((unsigned) fd < loop->nwatchers);
|
||||
|
||||
@ -843,7 +987,12 @@ void uv__set_process_title(const char* title) {
|
||||
}
|
||||
|
||||
int uv__io_fork(uv_loop_t* loop) {
|
||||
uv__platform_loop_delete(loop);
|
||||
/*
|
||||
Nullify the msg queue but don't close it because
|
||||
it is still being used by the parent.
|
||||
*/
|
||||
loop->ep = NULL;
|
||||
|
||||
uv__platform_loop_delete(loop);
|
||||
return uv__platform_loop_init(loop);
|
||||
}
|
||||
|
@ -300,3 +300,56 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
|
||||
else
|
||||
return uv__handle_type(handle->accepted_fd);
|
||||
}
|
||||
|
||||
|
||||
int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
|
||||
unsigned desired_mode;
|
||||
struct stat pipe_stat;
|
||||
char* name_buffer;
|
||||
size_t name_len;
|
||||
int r;
|
||||
|
||||
if (handle == NULL || uv__stream_fd(handle) == -1)
|
||||
return -EBADF;
|
||||
|
||||
if (mode != UV_READABLE &&
|
||||
mode != UV_WRITABLE &&
|
||||
mode != (UV_WRITABLE | UV_READABLE))
|
||||
return -EINVAL;
|
||||
|
||||
if (fstat(uv__stream_fd(handle), &pipe_stat) == -1)
|
||||
return -errno;
|
||||
|
||||
desired_mode = 0;
|
||||
if (mode & UV_READABLE)
|
||||
desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
|
||||
if (mode & UV_WRITABLE)
|
||||
desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
|
||||
|
||||
/* Exit early if pipe already has desired mode. */
|
||||
if ((pipe_stat.st_mode & desired_mode) == desired_mode)
|
||||
return 0;
|
||||
|
||||
pipe_stat.st_mode |= desired_mode;
|
||||
|
||||
/* Unfortunately fchmod does not work on all platforms, we will use chmod. */
|
||||
name_len = 0;
|
||||
r = uv_pipe_getsockname(handle, NULL, &name_len);
|
||||
if (r != UV_ENOBUFS)
|
||||
return r;
|
||||
|
||||
name_buffer = uv__malloc(name_len);
|
||||
if (name_buffer == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
r = uv_pipe_getsockname(handle, name_buffer, &name_len);
|
||||
if (r != 0) {
|
||||
uv__free(name_buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = chmod(name_buffer, pipe_stat.st_mode);
|
||||
uv__free(name_buffer);
|
||||
|
||||
return r != -1 ? 0 : -errno;
|
||||
}
|
||||
|
@ -33,8 +33,19 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
|
||||
handle = container_of(w, uv_poll_t, io_watcher);
|
||||
|
||||
if (events & POLLERR) {
|
||||
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP);
|
||||
/*
|
||||
* As documented in the kernel source fs/kernfs/file.c #780
|
||||
* poll will return POLLERR|POLLPRI in case of sysfs
|
||||
* polling. This does not happen in case of out-of-band
|
||||
* TCP messages.
|
||||
*
|
||||
* The above is the case on (at least) FreeBSD and Linux.
|
||||
*
|
||||
* So to properly determine a POLLPRI or a POLLERR we need
|
||||
* to check for both.
|
||||
*/
|
||||
if ((events & POLLERR) && !(events & UV__POLLPRI)) {
|
||||
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
uv__handle_stop(handle);
|
||||
handle->poll_cb(handle, -EBADF, 0);
|
||||
return;
|
||||
@ -43,6 +54,8 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
pevents = 0;
|
||||
if (events & POLLIN)
|
||||
pevents |= UV_READABLE;
|
||||
if (events & UV__POLLPRI)
|
||||
pevents |= UV_PRIORITIZED;
|
||||
if (events & POLLOUT)
|
||||
pevents |= UV_WRITABLE;
|
||||
if (events & UV__POLLRDHUP)
|
||||
@ -86,8 +99,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
|
||||
static void uv__poll_stop(uv_poll_t* handle) {
|
||||
uv__io_stop(handle->loop,
|
||||
&handle->io_watcher,
|
||||
POLLIN | POLLOUT | UV__POLLRDHUP);
|
||||
POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
|
||||
uv__handle_stop(handle);
|
||||
uv__platform_invalidate_fd(handle->loop, handle->io_watcher.fd);
|
||||
}
|
||||
|
||||
|
||||
@ -101,7 +115,8 @@ int uv_poll_stop(uv_poll_t* handle) {
|
||||
int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
|
||||
int events;
|
||||
|
||||
assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
||||
assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |
|
||||
UV_PRIORITIZED)) == 0);
|
||||
assert(!uv__is_closing(handle));
|
||||
|
||||
uv__poll_stop(handle);
|
||||
@ -112,6 +127,8 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
|
||||
events = 0;
|
||||
if (pevents & UV_READABLE)
|
||||
events |= POLLIN;
|
||||
if (pevents & UV_PRIORITIZED)
|
||||
events |= UV__POLLPRI;
|
||||
if (pevents & UV_WRITABLE)
|
||||
events |= POLLOUT;
|
||||
if (pevents & UV_DISCONNECT)
|
||||
|
@ -279,9 +279,12 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
int stdio_count,
|
||||
int (*pipes)[2],
|
||||
int error_fd) {
|
||||
sigset_t set;
|
||||
int close_fd;
|
||||
int use_fd;
|
||||
int err;
|
||||
int fd;
|
||||
int n;
|
||||
|
||||
if (options->flags & UV_PROCESS_DETACHED)
|
||||
setsid();
|
||||
@ -376,6 +379,31 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
environ = options->env;
|
||||
}
|
||||
|
||||
/* Reset signal disposition. Use a hard-coded limit because NSIG
|
||||
* is not fixed on Linux: it's either 32, 34 or 64, depending on
|
||||
* whether RT signals are enabled. We are not allowed to touch
|
||||
* RT signal handlers, glibc uses them internally.
|
||||
*/
|
||||
for (n = 1; n < 32; n += 1) {
|
||||
if (n == SIGKILL || n == SIGSTOP)
|
||||
continue; /* Can't be changed. */
|
||||
|
||||
if (SIG_ERR != signal(n, SIG_DFL))
|
||||
continue;
|
||||
|
||||
uv__write_int(error_fd, -errno);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
/* Reset signal mask. */
|
||||
sigemptyset(&set);
|
||||
err = pthread_sigmask(SIG_SETMASK, &set, NULL);
|
||||
|
||||
if (err != 0) {
|
||||
uv__write_int(error_fd, -err);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
execvp(options->file, options->args);
|
||||
uv__write_int(error_fd, -errno);
|
||||
_exit(127);
|
||||
@ -391,6 +419,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
return -ENOSYS;
|
||||
#else
|
||||
int signal_pipe[2] = { -1, -1 };
|
||||
int pipes_storage[8][2];
|
||||
int (*pipes)[2];
|
||||
int stdio_count;
|
||||
ssize_t r;
|
||||
@ -415,7 +444,10 @@ int uv_spawn(uv_loop_t* loop,
|
||||
stdio_count = 3;
|
||||
|
||||
err = -ENOMEM;
|
||||
pipes = uv__malloc(stdio_count * sizeof(*pipes));
|
||||
pipes = pipes_storage;
|
||||
if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
|
||||
pipes = uv__malloc(stdio_count * sizeof(*pipes));
|
||||
|
||||
if (pipes == NULL)
|
||||
goto error;
|
||||
|
||||
@ -520,7 +552,9 @@ int uv_spawn(uv_loop_t* loop,
|
||||
process->pid = pid;
|
||||
process->exit_cb = options->exit_cb;
|
||||
|
||||
uv__free(pipes);
|
||||
if (pipes != pipes_storage)
|
||||
uv__free(pipes);
|
||||
|
||||
return exec_errorno;
|
||||
|
||||
error:
|
||||
@ -534,7 +568,9 @@ error:
|
||||
if (pipes[i][1] != -1)
|
||||
uv__close_nocheckstdio(pipes[i][1]);
|
||||
}
|
||||
uv__free(pipes);
|
||||
|
||||
if (pipes != pipes_storage)
|
||||
uv__free(pipes);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
extern void uv__set_process_title(const char* title);
|
||||
|
||||
static uv_mutex_t process_title_mutex;
|
||||
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
|
||||
static void* args_mem;
|
||||
|
||||
static struct {
|
||||
@ -34,6 +36,11 @@ static struct {
|
||||
} process_title;
|
||||
|
||||
|
||||
static void init_process_title_mutex_once(void) {
|
||||
uv_mutex_init(&process_title_mutex);
|
||||
}
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
char** new_argv;
|
||||
size_t size;
|
||||
@ -81,12 +88,16 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
|
||||
|
||||
int uv_set_process_title(const char* title) {
|
||||
if (process_title.len == 0)
|
||||
return 0;
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
|
||||
/* No need to terminate, byte after is always '\0'. */
|
||||
strncpy(process_title.str, title, process_title.len);
|
||||
uv__set_process_title(title);
|
||||
if (process_title.len != 0) {
|
||||
/* No need to terminate, byte after is always '\0'. */
|
||||
strncpy(process_title.str, title, process_title.len);
|
||||
uv__set_process_title(title);
|
||||
}
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -95,12 +106,22 @@ int uv_set_process_title(const char* title) {
|
||||
int uv_get_process_title(char* buffer, size_t size) {
|
||||
if (buffer == NULL || size == 0)
|
||||
return -EINVAL;
|
||||
else if (size <= process_title.len)
|
||||
return -ENOBUFS;
|
||||
|
||||
memcpy(buffer, process_title.str, process_title.len + 1);
|
||||
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
|
||||
uv_mutex_lock(&process_title_mutex);
|
||||
|
||||
if (size <= process_title.len) {
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if (process_title.len != 0)
|
||||
memcpy(buffer, process_title.str, process_title.len + 1);
|
||||
|
||||
buffer[process_title.len] = '\0';
|
||||
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,121 +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.
|
||||
*/
|
||||
#include "uv-common.h"
|
||||
#include "pthread-barrier.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* TODO: support barrier_attr */
|
||||
int pthread_barrier_init(pthread_barrier_t* barrier,
|
||||
const void* barrier_attr,
|
||||
unsigned count) {
|
||||
int rc;
|
||||
_uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (barrier_attr != NULL)
|
||||
return ENOTSUP;
|
||||
|
||||
b = uv__malloc(sizeof(*b));
|
||||
if (b == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
b->in = 0;
|
||||
b->out = 0;
|
||||
b->threshold = count;
|
||||
|
||||
if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0)
|
||||
goto error2;
|
||||
if ((rc = pthread_cond_init(&b->cond, NULL)) != 0)
|
||||
goto error;
|
||||
|
||||
barrier->b = b;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
pthread_mutex_destroy(&b->mutex);
|
||||
error2:
|
||||
uv__free(b);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int pthread_barrier_wait(pthread_barrier_t* barrier) {
|
||||
int rc;
|
||||
_uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || barrier->b == NULL)
|
||||
return EINVAL;
|
||||
|
||||
b = barrier->b;
|
||||
/* Lock the 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) {
|
||||
b->in = 0;
|
||||
b->out = b->threshold - 1;
|
||||
rc = pthread_cond_signal(&b->cond);
|
||||
assert(rc == 0);
|
||||
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
/* 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 */
|
||||
b->out--;
|
||||
pthread_cond_signal(&b->cond);
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int pthread_barrier_destroy(pthread_barrier_t* barrier) {
|
||||
int rc;
|
||||
_uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || barrier->b == NULL)
|
||||
return EINVAL;
|
||||
|
||||
b = barrier->b;
|
||||
|
||||
if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
|
||||
return rc;
|
||||
|
||||
if (b->in > 0 || b->out > 0)
|
||||
rc = EBUSY;
|
||||
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pthread_cond_destroy(&b->cond);
|
||||
pthread_mutex_destroy(&b->mutex);
|
||||
uv__free(barrier->b);
|
||||
barrier->b = NULL;
|
||||
return 0;
|
||||
}
|
@ -514,7 +514,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
int err;
|
||||
|
||||
stream = container_of(w, uv_stream_t, io_watcher);
|
||||
assert(events == POLLIN);
|
||||
assert(events & POLLIN);
|
||||
assert(stream->accepted_fd == -1);
|
||||
assert(!(stream->flags & UV_CLOSING));
|
||||
|
||||
@ -750,6 +750,7 @@ static void uv__write(uv_stream_t* stream) {
|
||||
int iovmax;
|
||||
int iovcnt;
|
||||
ssize_t n;
|
||||
int err;
|
||||
|
||||
start:
|
||||
|
||||
@ -782,14 +783,21 @@ start:
|
||||
*/
|
||||
|
||||
if (req->send_handle) {
|
||||
int fd_to_send;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
|
||||
union {
|
||||
char data[64];
|
||||
struct cmsghdr alias;
|
||||
} scratch;
|
||||
|
||||
if (uv__is_closing(req->send_handle)) {
|
||||
err = -EBADF;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
|
||||
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
|
||||
assert(fd_to_send >= 0);
|
||||
@ -851,15 +859,9 @@ start:
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
/* Error */
|
||||
req->error = -errno;
|
||||
uv__write_req_finish(req);
|
||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
|
||||
if (!uv__io_active(&stream->io_watcher, POLLIN))
|
||||
uv__handle_stop(stream);
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
return;
|
||||
if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENOBUFS) {
|
||||
err = -errno;
|
||||
goto error;
|
||||
} else if (stream->flags & UV_STREAM_BLOCKING) {
|
||||
/* If this is a blocking stream, try again. */
|
||||
goto start;
|
||||
@ -923,6 +925,16 @@ start:
|
||||
|
||||
/* Notify select() thread about state change */
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
req->error = err;
|
||||
uv__write_req_finish(req);
|
||||
uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
|
||||
if (!uv__io_active(&stream->io_watcher, POLLIN))
|
||||
uv__handle_stop(stream);
|
||||
uv__stream_osx_interrupt_select(stream);
|
||||
}
|
||||
|
||||
|
||||
@ -1249,8 +1261,9 @@ static void uv__read(uv_stream_t* stream) {
|
||||
|
||||
|
||||
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
||||
assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE) &&
|
||||
"uv_shutdown (unix) only supports uv_handle_t right now");
|
||||
assert(stream->type == UV_TCP ||
|
||||
stream->type == UV_TTY ||
|
||||
stream->type == UV_NAMED_PIPE);
|
||||
|
||||
if (!(stream->flags & UV_STREAM_WRITABLE) ||
|
||||
stream->flags & UV_STREAM_SHUT ||
|
||||
|
@ -751,7 +751,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) {
|
||||
return 1;
|
||||
if (ent->ifa_addr == NULL)
|
||||
return 1;
|
||||
if (ent->ifa_addr->sa_family == PF_PACKET)
|
||||
if (ent->ifa_addr->sa_family != AF_INET &&
|
||||
ent->ifa_addr->sa_family != AF_INET6)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@ -760,7 +761,6 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
uv_interface_address_t* address;
|
||||
struct ifaddrs* addrs;
|
||||
struct ifaddrs* ent;
|
||||
int i;
|
||||
|
||||
if (getifaddrs(&addrs))
|
||||
return -errno;
|
||||
|
@ -28,15 +28,12 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
|
||||
static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
|
||||
struct sockaddr_storage saddr;
|
||||
socklen_t slen;
|
||||
int sockfd;
|
||||
int err;
|
||||
|
||||
if (domain == AF_UNSPEC || uv__stream_fd(handle) != -1) {
|
||||
handle->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = uv__socket(domain, SOCK_STREAM, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
@ -48,10 +45,74 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (flags & UV_HANDLE_BOUND) {
|
||||
/* Bind this new socket to an arbitrary port */
|
||||
slen = sizeof(saddr);
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen);
|
||||
if (err) {
|
||||
uv__close(sockfd);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen);
|
||||
if (err) {
|
||||
uv__close(sockfd);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
|
||||
struct sockaddr_storage saddr;
|
||||
socklen_t slen;
|
||||
|
||||
if (domain == AF_UNSPEC) {
|
||||
handle->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uv__stream_fd(handle) != -1) {
|
||||
|
||||
if (flags & UV_HANDLE_BOUND) {
|
||||
|
||||
if (handle->flags & UV_HANDLE_BOUND) {
|
||||
/* It is already bound to a port. */
|
||||
handle->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Query to see if tcp socket is bound. */
|
||||
slen = sizeof(saddr);
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
|
||||
return -errno;
|
||||
|
||||
if ((saddr.ss_family == AF_INET6 &&
|
||||
((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
|
||||
(saddr.ss_family == AF_INET &&
|
||||
((struct sockaddr_in*) &saddr)->sin_port != 0)) {
|
||||
/* Handle is already bound to a port. */
|
||||
handle->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Bind to arbitrary port */
|
||||
if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
|
||||
return -errno;
|
||||
}
|
||||
|
||||
handle->flags |= flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new_socket(handle, domain, flags);
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
|
||||
int domain;
|
||||
|
||||
@ -260,6 +321,7 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
|
||||
|
||||
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
|
||||
static int single_accept = -1;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
if (tcp->delayed_error)
|
||||
@ -273,30 +335,17 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
|
||||
if (single_accept)
|
||||
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
|
||||
|
||||
err = maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
#ifdef __MVS__
|
||||
flags = UV_STREAM_READABLE;
|
||||
#if defined(__MVS__)
|
||||
/* on zOS the listen call does not bind automatically
|
||||
if the socket is unbound. Hence the manual binding to
|
||||
an arbitrary port is required to be done manually
|
||||
*/
|
||||
|
||||
if (!(tcp->flags & UV_HANDLE_BOUND)) {
|
||||
struct sockaddr_storage saddr;
|
||||
socklen_t slen = sizeof(saddr);
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
|
||||
if (getsockname(tcp->io_watcher.fd, (struct sockaddr*) &saddr, &slen))
|
||||
return -errno;
|
||||
|
||||
if (bind(tcp->io_watcher.fd, (struct sockaddr*) &saddr, slen))
|
||||
return -errno;
|
||||
|
||||
tcp->flags |= UV_HANDLE_BOUND;
|
||||
}
|
||||
#endif
|
||||
flags |= UV_HANDLE_BOUND;
|
||||
#endif
|
||||
err = maybe_new_socket(tcp, AF_INET, flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (listen(tcp->io_watcher.fd, backlog))
|
||||
return -errno;
|
||||
|
@ -41,37 +41,160 @@
|
||||
#define NANOSEC ((uint64_t) 1e9)
|
||||
|
||||
|
||||
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
int err;
|
||||
pthread_attr_t* attr;
|
||||
#if defined(__APPLE__)
|
||||
pthread_attr_t attr_storage;
|
||||
struct rlimit lim;
|
||||
#if defined(UV__PTHREAD_BARRIER_FALLBACK)
|
||||
/* TODO: support barrier_attr */
|
||||
int pthread_barrier_init(pthread_barrier_t* barrier,
|
||||
const void* barrier_attr,
|
||||
unsigned count) {
|
||||
int rc;
|
||||
_uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || count == 0)
|
||||
return EINVAL;
|
||||
|
||||
if (barrier_attr != NULL)
|
||||
return ENOTSUP;
|
||||
|
||||
b = uv__malloc(sizeof(*b));
|
||||
if (b == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
b->in = 0;
|
||||
b->out = 0;
|
||||
b->threshold = count;
|
||||
|
||||
if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0)
|
||||
goto error2;
|
||||
if ((rc = pthread_cond_init(&b->cond, NULL)) != 0)
|
||||
goto error;
|
||||
|
||||
barrier->b = b;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
pthread_mutex_destroy(&b->mutex);
|
||||
error2:
|
||||
uv__free(b);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int pthread_barrier_wait(pthread_barrier_t* barrier) {
|
||||
int rc;
|
||||
_uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || barrier->b == NULL)
|
||||
return EINVAL;
|
||||
|
||||
b = barrier->b;
|
||||
/* Lock the 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) {
|
||||
b->in = 0;
|
||||
b->out = b->threshold - 1;
|
||||
rc = pthread_cond_signal(&b->cond);
|
||||
assert(rc == 0);
|
||||
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
/* 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 */
|
||||
b->out--;
|
||||
pthread_cond_signal(&b->cond);
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int pthread_barrier_destroy(pthread_barrier_t* barrier) {
|
||||
int rc;
|
||||
_uv_barrier* b;
|
||||
|
||||
if (barrier == NULL || barrier->b == NULL)
|
||||
return EINVAL;
|
||||
|
||||
b = barrier->b;
|
||||
|
||||
if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
|
||||
return rc;
|
||||
|
||||
if (b->in > 0 || b->out > 0)
|
||||
rc = EBUSY;
|
||||
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pthread_cond_destroy(&b->cond);
|
||||
pthread_mutex_destroy(&b->mutex);
|
||||
uv__free(barrier->b);
|
||||
barrier->b = NULL;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* On OSX threads other than the main thread are created with a reduced stack
|
||||
* size by default, adjust it to RLIMIT_STACK.
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
if (getrlimit(RLIMIT_STACK, &lim))
|
||||
abort();
|
||||
|
||||
attr = &attr_storage;
|
||||
if (pthread_attr_init(attr))
|
||||
/* On MacOS, threads other than the main thread are created with a reduced
|
||||
* stack size by default. Adjust to RLIMIT_STACK aligned to the page size.
|
||||
*
|
||||
* On Linux, threads created by musl have a much smaller stack than threads
|
||||
* created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency.
|
||||
*/
|
||||
static size_t thread_stack_size(void) {
|
||||
#if defined(__APPLE__) || defined(__linux__)
|
||||
struct rlimit lim;
|
||||
|
||||
if (getrlimit(RLIMIT_STACK, &lim))
|
||||
abort();
|
||||
|
||||
if (lim.rlim_cur != RLIM_INFINITY) {
|
||||
/* pthread_attr_setstacksize() expects page-aligned values. */
|
||||
lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
|
||||
|
||||
if (lim.rlim_cur >= PTHREAD_STACK_MIN)
|
||||
if (pthread_attr_setstacksize(attr, lim.rlim_cur))
|
||||
abort();
|
||||
return lim.rlim_cur;
|
||||
}
|
||||
#else
|
||||
attr = NULL;
|
||||
#endif
|
||||
|
||||
#if !defined(__linux__)
|
||||
return 0;
|
||||
#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
|
||||
return 4 << 20; /* glibc default. */
|
||||
#else
|
||||
return 2 << 20; /* glibc default. */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
int err;
|
||||
size_t stack_size;
|
||||
pthread_attr_t* attr;
|
||||
pthread_attr_t attr_storage;
|
||||
|
||||
attr = NULL;
|
||||
stack_size = thread_stack_size();
|
||||
|
||||
if (stack_size > 0) {
|
||||
attr = &attr_storage;
|
||||
|
||||
if (pthread_attr_init(attr))
|
||||
abort();
|
||||
|
||||
if (pthread_attr_setstacksize(attr, stack_size))
|
||||
abort();
|
||||
}
|
||||
|
||||
err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
|
||||
|
||||
if (attr != NULL)
|
||||
@ -118,6 +241,25 @@ int uv_mutex_init(uv_mutex_t* mutex) {
|
||||
}
|
||||
|
||||
|
||||
int uv_mutex_init_recursive(uv_mutex_t* mutex) {
|
||||
pthread_mutexattr_t attr;
|
||||
int err;
|
||||
|
||||
if (pthread_mutexattr_init(&attr))
|
||||
abort();
|
||||
|
||||
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
|
||||
abort();
|
||||
|
||||
err = pthread_mutex_init(mutex, &attr);
|
||||
|
||||
if (pthread_mutexattr_destroy(&attr))
|
||||
abort();
|
||||
|
||||
return -err;
|
||||
}
|
||||
|
||||
|
||||
void uv_mutex_destroy(uv_mutex_t* mutex) {
|
||||
if (pthread_mutex_destroy(mutex))
|
||||
abort();
|
||||
@ -281,18 +423,20 @@ int uv_sem_trywait(uv_sem_t* sem) {
|
||||
|
||||
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
|
||||
uv_sem_t semid;
|
||||
struct sembuf buf;
|
||||
int err;
|
||||
union {
|
||||
int val;
|
||||
struct semid_ds* buf;
|
||||
unsigned short* array;
|
||||
} arg;
|
||||
|
||||
buf.sem_num = 0;
|
||||
buf.sem_op = value;
|
||||
buf.sem_flg = 0;
|
||||
|
||||
semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
|
||||
if (semid == -1)
|
||||
return -errno;
|
||||
|
||||
if (-1 == semop(semid, &buf, 1)) {
|
||||
arg.val = value;
|
||||
if (-1 == semctl(semid, 0, SETVAL, arg)) {
|
||||
err = errno;
|
||||
if (-1 == semctl(*sem, 0, IPC_RMID))
|
||||
abort();
|
||||
@ -424,7 +568,7 @@ int uv_cond_init(uv_cond_t* cond) {
|
||||
if (err)
|
||||
return -err;
|
||||
|
||||
#if !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
|
||||
#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
|
||||
err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
|
||||
if (err)
|
||||
goto error2;
|
||||
@ -511,7 +655,8 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
|
||||
timeout += uv__hrtime(UV_CLOCK_PRECISE);
|
||||
ts.tv_sec = timeout / NANOSEC;
|
||||
ts.tv_nsec = timeout % NANOSEC;
|
||||
#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
|
||||
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
|
||||
|
||||
/*
|
||||
* The bionic pthread implementation doesn't support CLOCK_MONOTONIC,
|
||||
* but has this alternative function instead.
|
||||
@ -519,7 +664,7 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
|
||||
r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
|
||||
#else
|
||||
r = pthread_cond_timedwait(cond, mutex, &ts);
|
||||
#endif /* __ANDROID__ */
|
||||
#endif /* __ANDROID_API__ */
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -48,6 +48,42 @@ static int uv__tty_is_slave(const int fd) {
|
||||
char dummy[256];
|
||||
|
||||
result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0;
|
||||
#elif defined(__NetBSD__)
|
||||
/*
|
||||
* NetBSD as an extension returns with ptsname(3) and ptsname_r(3) the slave
|
||||
* device name for both descriptors, the master one and slave one.
|
||||
*
|
||||
* Implement function to compare major device number with pts devices.
|
||||
*
|
||||
* The major numbers are machine-dependent, on NetBSD/amd64 they are
|
||||
* respectively:
|
||||
* - master tty: ptc - major 6
|
||||
* - slave tty: pts - major 5
|
||||
*/
|
||||
|
||||
struct stat sb;
|
||||
/* Lookup device's major for the pts driver and cache it. */
|
||||
static devmajor_t pts = NODEVMAJOR;
|
||||
|
||||
if (pts == NODEVMAJOR) {
|
||||
pts = getdevmajor("pts", S_IFCHR);
|
||||
if (pts == NODEVMAJOR)
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Lookup stat structure behind the file descriptor. */
|
||||
if (fstat(fd, &sb) != 0)
|
||||
abort();
|
||||
|
||||
/* Assert character device. */
|
||||
if (!S_ISCHR(sb.st_mode))
|
||||
abort();
|
||||
|
||||
/* Assert valid major. */
|
||||
if (major(sb.st_rdev) == NODEVMAJOR)
|
||||
abort();
|
||||
|
||||
result = (pts == major(sb.st_rdev));
|
||||
#else
|
||||
/* Fallback to ptsname
|
||||
*/
|
||||
|
@ -237,8 +237,10 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
|
||||
size = sendmsg(handle->io_watcher.fd, &h, 0);
|
||||
} while (size == -1 && errno == EINTR);
|
||||
|
||||
if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
|
||||
break;
|
||||
if (size == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
|
||||
break;
|
||||
}
|
||||
|
||||
req->status = (size == -1 ? -errno : size);
|
||||
|
||||
@ -472,7 +474,7 @@ int uv__udp_try_send(uv_udp_t* handle,
|
||||
} while (size == -1 && errno == EINTR);
|
||||
|
||||
if (size == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
|
||||
return -EAGAIN;
|
||||
else
|
||||
return -errno;
|
||||
|
96
Utilities/cmlibuv/src/uv-data-getter-setters.c
Normal file
96
Utilities/cmlibuv/src/uv-data-getter-setters.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include "uv.h"
|
||||
|
||||
const char* uv_handle_type_name(uv_handle_type type) {
|
||||
switch (type) {
|
||||
#define XX(uc,lc) case UV_##uc: return #lc;
|
||||
UV_HANDLE_TYPE_MAP(XX)
|
||||
#undef XX
|
||||
case UV_FILE: return "file";
|
||||
case UV_HANDLE_TYPE_MAX:
|
||||
case UV_UNKNOWN_HANDLE: return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uv_handle_type uv_handle_get_type(const uv_handle_t* handle) {
|
||||
return handle->type;
|
||||
}
|
||||
|
||||
void* uv_handle_get_data(const uv_handle_t* handle) {
|
||||
return handle->data;
|
||||
}
|
||||
|
||||
uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle) {
|
||||
return handle->loop;
|
||||
}
|
||||
|
||||
void uv_handle_set_data(uv_handle_t* handle, void* data) {
|
||||
handle->data = data;
|
||||
}
|
||||
|
||||
const char* uv_req_type_name(uv_req_type type) {
|
||||
switch (type) {
|
||||
#define XX(uc,lc) case UV_##uc: return #lc;
|
||||
UV_REQ_TYPE_MAP(XX)
|
||||
#undef XX
|
||||
case UV_REQ_TYPE_MAX:
|
||||
case UV_UNKNOWN_REQ: return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uv_req_type uv_req_get_type(const uv_req_t* req) {
|
||||
return req->type;
|
||||
}
|
||||
|
||||
void* uv_req_get_data(const uv_req_t* req) {
|
||||
return req->data;
|
||||
}
|
||||
|
||||
void uv_req_set_data(uv_req_t* req, void* data) {
|
||||
req->data = data;
|
||||
}
|
||||
|
||||
size_t uv_stream_get_write_queue_size(const uv_stream_t* stream) {
|
||||
return stream->write_queue_size;
|
||||
}
|
||||
|
||||
size_t uv_udp_get_send_queue_size(const uv_udp_t* handle) {
|
||||
return handle->send_queue_size;
|
||||
}
|
||||
|
||||
size_t uv_udp_get_send_queue_count(const uv_udp_t* handle) {
|
||||
return handle->send_queue_count;
|
||||
}
|
||||
|
||||
uv_pid_t uv_process_get_pid(const uv_process_t* proc) {
|
||||
return proc->pid;
|
||||
}
|
||||
|
||||
uv_fs_type uv_fs_get_type(const uv_fs_t* req) {
|
||||
return req->fs_type;
|
||||
}
|
||||
|
||||
ssize_t uv_fs_get_result(const uv_fs_t* req) {
|
||||
return req->result;
|
||||
}
|
||||
|
||||
void* uv_fs_get_ptr(const uv_fs_t* req) {
|
||||
return req->ptr;
|
||||
}
|
||||
|
||||
const char* uv_fs_get_path(const uv_fs_t* req) {
|
||||
return req->path;
|
||||
}
|
||||
|
||||
uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req) {
|
||||
return &req->statbuf;
|
||||
}
|
||||
|
||||
void* uv_loop_get_data(const uv_loop_t* loop) {
|
||||
return loop->data;
|
||||
}
|
||||
|
||||
void uv_loop_set_data(uv_loop_t* loop, void* data) {
|
||||
loop->data = data;
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
|
||||
static int uv__dlerror(uv_lib_t* lib, int errorno);
|
||||
static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno);
|
||||
|
||||
|
||||
int uv_dlopen(const char* filename, uv_lib_t* lib) {
|
||||
@ -37,12 +37,12 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) {
|
||||
-1,
|
||||
filename_w,
|
||||
ARRAY_SIZE(filename_w))) {
|
||||
return uv__dlerror(lib, GetLastError());
|
||||
return uv__dlerror(lib, filename, GetLastError());
|
||||
}
|
||||
|
||||
lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
if (lib->handle == NULL) {
|
||||
return uv__dlerror(lib, GetLastError());
|
||||
return uv__dlerror(lib, filename, GetLastError());
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -65,7 +65,7 @@ void uv_dlclose(uv_lib_t* lib) {
|
||||
|
||||
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
|
||||
*ptr = (void*) GetProcAddress(lib->handle, name);
|
||||
return uv__dlerror(lib, *ptr ? 0 : GetLastError());
|
||||
return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());
|
||||
}
|
||||
|
||||
|
||||
@ -88,31 +88,46 @@ static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
|
||||
|
||||
|
||||
|
||||
static int uv__dlerror(uv_lib_t* lib, int errorno) {
|
||||
static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) {
|
||||
DWORD_PTR arg;
|
||||
DWORD res;
|
||||
char* msg;
|
||||
|
||||
if (lib->errmsg) {
|
||||
LocalFree((void*)lib->errmsg);
|
||||
LocalFree(lib->errmsg);
|
||||
lib->errmsg = NULL;
|
||||
}
|
||||
|
||||
if (errorno) {
|
||||
if (errorno == 0)
|
||||
return 0;
|
||||
|
||||
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
|
||||
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
||||
(LPSTR) &lib->errmsg, 0, NULL);
|
||||
|
||||
if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
|
||||
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
|
||||
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
||||
(LPSTR) &lib->errmsg, 0, NULL);
|
||||
if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
|
||||
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
|
||||
0, (LPSTR) &lib->errmsg, 0, NULL);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
uv__format_fallback_error(lib, errorno);
|
||||
}
|
||||
0, (LPSTR) &lib->errmsg, 0, NULL);
|
||||
}
|
||||
|
||||
return errorno ? -1 : 0;
|
||||
if (res && errorno == ERROR_BAD_EXE_FORMAT && strstr(lib->errmsg, "%1")) {
|
||||
msg = lib->errmsg;
|
||||
lib->errmsg = NULL;
|
||||
arg = (DWORD_PTR) filename;
|
||||
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
||||
FORMAT_MESSAGE_FROM_STRING,
|
||||
msg,
|
||||
0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) &arg);
|
||||
LocalFree(msg);
|
||||
}
|
||||
|
||||
if (!res)
|
||||
uv__format_fallback_error(lib, errorno);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ void uv_fatal_error(const int errorno, const char* syscall) {
|
||||
LocalFree(buf);
|
||||
}
|
||||
|
||||
*((char*)NULL) = 0xff; /* Force debug break */
|
||||
DebugBreak();
|
||||
abort();
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,8 @@
|
||||
/* EAI_* constants. */
|
||||
#include <winsock2.h>
|
||||
|
||||
/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */
|
||||
#include <iphlpapi.h>
|
||||
|
||||
int uv__getaddrinfo_translate_error(int sys_err) {
|
||||
switch (sys_err) {
|
||||
@ -73,6 +75,9 @@ int uv__getaddrinfo_translate_error(int sys_err) {
|
||||
/* Do we need different versions of this for different architectures? */
|
||||
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
|
||||
|
||||
#ifndef NDIS_IF_MAX_STRING_SIZE
|
||||
#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE
|
||||
#endif
|
||||
|
||||
static void uv__getaddrinfo_work(struct uv__work* w) {
|
||||
uv_getaddrinfo_t* req;
|
||||
@ -380,3 +385,69 @@ error:
|
||||
}
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
|
||||
NET_LUID luid;
|
||||
wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
|
||||
DWORD bufsize;
|
||||
int r;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
r = ConvertInterfaceIndexToLuid(ifindex, &luid);
|
||||
|
||||
if (r != 0)
|
||||
return uv_translate_sys_error(r);
|
||||
|
||||
r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
|
||||
|
||||
if (r != 0)
|
||||
return uv_translate_sys_error(r);
|
||||
|
||||
/* Check how much space we need */
|
||||
bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (bufsize == 0) {
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
} else if (bufsize > *size) {
|
||||
*size = bufsize;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
/* Convert to UTF-8 */
|
||||
bufsize = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
wname,
|
||||
-1,
|
||||
buffer,
|
||||
*size,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (bufsize == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
|
||||
*size = bufsize - 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
|
||||
int r;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
r = snprintf(buffer, *size, "%d", ifindex);
|
||||
|
||||
if (r < 0)
|
||||
return uv_translate_sys_error(r);
|
||||
|
||||
if (r >= (int) *size) {
|
||||
*size = r + 1;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
*size = r;
|
||||
return 0;
|
||||
}
|
||||
|
@ -152,3 +152,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
|
||||
int uv_is_closing(const uv_handle_t* handle) {
|
||||
return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED));
|
||||
}
|
||||
|
||||
|
||||
uv_os_fd_t uv_get_osfhandle(int fd) {
|
||||
return uv__get_osfhandle(fd);
|
||||
}
|
||||
|
@ -330,7 +330,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
|
||||
void uv__util_init(void);
|
||||
|
||||
uint64_t uv__hrtime(double scale);
|
||||
int uv_parent_pid(void);
|
||||
int uv_current_pid(void);
|
||||
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
|
||||
int uv__getpwuid_r(uv_passwd_t* pwd);
|
||||
|
@ -31,6 +31,9 @@
|
||||
#include "stream-inl.h"
|
||||
#include "req-inl.h"
|
||||
|
||||
#include <aclapi.h>
|
||||
#include <accctrl.h>
|
||||
|
||||
typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t;
|
||||
|
||||
struct uv__ipc_queue_item_s {
|
||||
@ -202,7 +205,7 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
|
||||
uv_unique_pipe_name(ptr, name, nameSize);
|
||||
|
||||
pipeHandle = CreateNamedPipeA(name,
|
||||
access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
|
||||
access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
|
||||
NULL);
|
||||
|
||||
@ -534,7 +537,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
|
||||
*/
|
||||
handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE,
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
|
||||
|
||||
@ -803,7 +806,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
|
||||
|
||||
req->pipeHandle = CreateNamedPipeW(handle->name,
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
|
||||
|
||||
@ -968,27 +971,31 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
|
||||
uv_mutex_unlock(m);
|
||||
}
|
||||
restart_readfile:
|
||||
result = ReadFile(handle->handle,
|
||||
&uv_zero_,
|
||||
0,
|
||||
&bytes,
|
||||
NULL);
|
||||
if (!result) {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_OPERATION_ABORTED &&
|
||||
handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
|
||||
if (handle->flags & UV_HANDLE_READING) {
|
||||
/* just a brief break to do something else */
|
||||
handle->pipe.conn.readfile_thread = NULL;
|
||||
/* resume after it is finished */
|
||||
uv_mutex_lock(m);
|
||||
handle->pipe.conn.readfile_thread = hThread;
|
||||
uv_mutex_unlock(m);
|
||||
goto restart_readfile;
|
||||
} else {
|
||||
result = 1; /* successfully stopped reading */
|
||||
if (handle->flags & UV_HANDLE_READING) {
|
||||
result = ReadFile(handle->handle,
|
||||
&uv_zero_,
|
||||
0,
|
||||
&bytes,
|
||||
NULL);
|
||||
if (!result) {
|
||||
err = GetLastError();
|
||||
if (err == ERROR_OPERATION_ABORTED &&
|
||||
handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
|
||||
if (handle->flags & UV_HANDLE_READING) {
|
||||
/* just a brief break to do something else */
|
||||
handle->pipe.conn.readfile_thread = NULL;
|
||||
/* resume after it is finished */
|
||||
uv_mutex_lock(m);
|
||||
handle->pipe.conn.readfile_thread = hThread;
|
||||
uv_mutex_unlock(m);
|
||||
goto restart_readfile;
|
||||
} else {
|
||||
result = 1; /* successfully stopped reading */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = 1; /* successfully aborted read before it even started */
|
||||
}
|
||||
if (hThread) {
|
||||
assert(hThread == handle->pipe.conn.readfile_thread);
|
||||
@ -1515,7 +1522,10 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
|
||||
|
||||
static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
|
||||
int error, uv_buf_t buf) {
|
||||
if (error == ERROR_BROKEN_PIPE) {
|
||||
if (error == ERROR_OPERATION_ABORTED) {
|
||||
/* do nothing (equivalent to EINTR) */
|
||||
}
|
||||
else if (error == ERROR_BROKEN_PIPE) {
|
||||
uv_pipe_read_eof(loop, handle, buf);
|
||||
} else {
|
||||
uv_pipe_read_error(loop, handle, error, buf);
|
||||
@ -1906,6 +1916,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
||||
if (os_handle == INVALID_HANDLE_VALUE)
|
||||
return UV_EBADF;
|
||||
|
||||
uv__once_init();
|
||||
/* In order to avoid closing a stdio file descriptor 0-2, duplicate the
|
||||
* underlying OS handle and forget about the original fd.
|
||||
* We could also opt to use the original OS handle and just never close it,
|
||||
@ -1961,7 +1972,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
|
||||
|
||||
if (pipe->ipc) {
|
||||
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
|
||||
pipe->pipe.conn.ipc_pid = uv_parent_pid();
|
||||
pipe->pipe.conn.ipc_pid = uv_os_getppid();
|
||||
assert(pipe->pipe.conn.ipc_pid != -1);
|
||||
}
|
||||
return 0;
|
||||
@ -1979,6 +1990,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
unsigned int name_len;
|
||||
int err;
|
||||
|
||||
uv__once_init();
|
||||
name_info = NULL;
|
||||
|
||||
if (handle->handle == INVALID_HANDLE_VALUE) {
|
||||
@ -2123,3 +2135,80 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
|
||||
else
|
||||
return UV_TCP;
|
||||
}
|
||||
|
||||
int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
|
||||
SID_IDENTIFIER_AUTHORITY sid_world = SECURITY_WORLD_SID_AUTHORITY;
|
||||
PACL old_dacl, new_dacl;
|
||||
PSECURITY_DESCRIPTOR sd;
|
||||
EXPLICIT_ACCESS ea;
|
||||
PSID everyone;
|
||||
int error;
|
||||
|
||||
if (handle == NULL || handle->handle == INVALID_HANDLE_VALUE)
|
||||
return UV_EBADF;
|
||||
|
||||
if (mode != UV_READABLE &&
|
||||
mode != UV_WRITABLE &&
|
||||
mode != (UV_WRITABLE | UV_READABLE))
|
||||
return UV_EINVAL;
|
||||
|
||||
if (!AllocateAndInitializeSid(&sid_world,
|
||||
1,
|
||||
SECURITY_WORLD_RID,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
&everyone)) {
|
||||
error = GetLastError();
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (GetSecurityInfo(handle->handle,
|
||||
SE_KERNEL_OBJECT,
|
||||
DACL_SECURITY_INFORMATION,
|
||||
NULL,
|
||||
NULL,
|
||||
&old_dacl,
|
||||
NULL,
|
||||
&sd)) {
|
||||
error = GetLastError();
|
||||
goto clean_sid;
|
||||
}
|
||||
|
||||
memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
|
||||
if (mode & UV_READABLE)
|
||||
ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
|
||||
if (mode & UV_WRITABLE)
|
||||
ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
||||
ea.grfAccessPermissions |= SYNCHRONIZE;
|
||||
ea.grfAccessMode = SET_ACCESS;
|
||||
ea.grfInheritance = NO_INHERITANCE;
|
||||
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
|
||||
ea.Trustee.ptstrName = (LPTSTR)everyone;
|
||||
|
||||
if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) {
|
||||
error = GetLastError();
|
||||
goto clean_sd;
|
||||
}
|
||||
|
||||
if (SetSecurityInfo(handle->handle,
|
||||
SE_KERNEL_OBJECT,
|
||||
DACL_SECURITY_INFORMATION,
|
||||
NULL,
|
||||
NULL,
|
||||
new_dacl,
|
||||
NULL)) {
|
||||
error = GetLastError();
|
||||
goto clean_dacl;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
|
||||
clean_dacl:
|
||||
LocalFree((HLOCAL) new_dacl);
|
||||
clean_sd:
|
||||
LocalFree((HLOCAL) sd);
|
||||
clean_sid:
|
||||
FreeSid(everyone);
|
||||
done:
|
||||
return uv_translate_sys_error(error);
|
||||
}
|
||||
|
@ -405,8 +405,15 @@ static WCHAR* search_path(const WCHAR *file,
|
||||
/* Next slice starts just after where the previous one ended */
|
||||
dir_start = dir_end;
|
||||
|
||||
/* If path is quoted, find quote end */
|
||||
if (*dir_start == L'"' || *dir_start == L'\'') {
|
||||
dir_end = wcschr(dir_start + 1, *dir_start);
|
||||
if (dir_end == NULL) {
|
||||
dir_end = wcschr(dir_start, L'\0');
|
||||
}
|
||||
}
|
||||
/* Slice until the next ; or \0 is found */
|
||||
dir_end = wcschr(dir_start, L';');
|
||||
dir_end = wcschr(dir_end, L';');
|
||||
if (dir_end == NULL) {
|
||||
dir_end = wcschr(dir_start, L'\0');
|
||||
}
|
||||
@ -1051,15 +1058,18 @@ int uv_spawn(uv_loop_t* loop,
|
||||
startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
|
||||
startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
|
||||
|
||||
process_flags = CREATE_UNICODE_ENVIRONMENT;
|
||||
|
||||
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
|
||||
/* Use SW_HIDE to avoid any potential process window. */
|
||||
startup.wShowWindow = SW_HIDE;
|
||||
|
||||
/* Hide console windows. */
|
||||
process_flags |= CREATE_NO_WINDOW;
|
||||
} else {
|
||||
startup.wShowWindow = SW_SHOWDEFAULT;
|
||||
}
|
||||
|
||||
process_flags = CREATE_UNICODE_ENVIRONMENT;
|
||||
|
||||
if (options->flags & UV_PROCESS_DETACHED) {
|
||||
/* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
|
||||
* means that libuv might not let you create a fully daemonized process
|
||||
@ -1163,6 +1173,10 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
|
||||
static int uv__kill(HANDLE process_handle, int signum) {
|
||||
if (signum < 0 || signum >= NSIG) {
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
switch (signum) {
|
||||
case SIGTERM:
|
||||
case SIGKILL:
|
||||
@ -1227,8 +1241,15 @@ int uv_process_kill(uv_process_t* process, int signum) {
|
||||
|
||||
int uv_kill(int pid, int signum) {
|
||||
int err;
|
||||
HANDLE process_handle = OpenProcess(PROCESS_TERMINATE |
|
||||
PROCESS_QUERY_INFORMATION, FALSE, pid);
|
||||
HANDLE process_handle;
|
||||
|
||||
if (pid == 0) {
|
||||
process_handle = GetCurrentProcess();
|
||||
} else {
|
||||
process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
|
||||
FALSE,
|
||||
pid);
|
||||
}
|
||||
|
||||
if (process_handle == NULL) {
|
||||
err = GetLastError();
|
||||
|
@ -64,7 +64,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
|
||||
}
|
||||
|
||||
|
||||
RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare);
|
||||
RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare)
|
||||
|
||||
|
||||
/*
|
||||
|
@ -36,6 +36,7 @@ INLINE static void uv_stream_init(uv_loop_t* loop,
|
||||
uv__handle_init(loop, (uv_handle_t*) handle, type);
|
||||
handle->write_queue_size = 0;
|
||||
handle->activecnt = 0;
|
||||
handle->stream.conn.shutdown_req = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -47,8 +48,6 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
|
||||
handle->read_req.event_handle = NULL;
|
||||
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
|
||||
handle->read_req.data = handle;
|
||||
|
||||
handle->stream.conn.shutdown_req = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -747,10 +747,15 @@ static int uv_tcp_try_connect(uv_connect_t* req,
|
||||
uv_connect_cb cb) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
const struct sockaddr* bind_addr;
|
||||
struct sockaddr_storage converted;
|
||||
BOOL success;
|
||||
DWORD bytes;
|
||||
int err;
|
||||
|
||||
err = uv__convert_to_localhost_if_unspecified(addr, &converted);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (handle->delayed_error) {
|
||||
return handle->delayed_error;
|
||||
}
|
||||
@ -782,12 +787,12 @@ static int uv_tcp_try_connect(uv_connect_t* req,
|
||||
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
|
||||
|
||||
success = handle->tcp.conn.func_connectex(handle->socket,
|
||||
addr,
|
||||
addrlen,
|
||||
NULL,
|
||||
0,
|
||||
&bytes,
|
||||
&req->u.io.overlapped);
|
||||
(const struct sockaddr*) &converted,
|
||||
addrlen,
|
||||
NULL,
|
||||
0,
|
||||
&bytes,
|
||||
&req->u.io.overlapped);
|
||||
|
||||
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
|
||||
/* Process the req without IOCP. */
|
||||
@ -1446,6 +1451,8 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
|
||||
WSAPROTOCOL_INFOW protocol_info;
|
||||
int opt_len;
|
||||
int err;
|
||||
struct sockaddr_storage saddr;
|
||||
int saddr_len;
|
||||
|
||||
/* Detect the address family of the socket. */
|
||||
opt_len = (int) sizeof protocol_info;
|
||||
@ -1466,6 +1473,19 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
/* Support already active socket. */
|
||||
saddr_len = sizeof(saddr);
|
||||
if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) {
|
||||
/* Socket is already bound. */
|
||||
handle->flags |= UV_HANDLE_BOUND;
|
||||
saddr_len = sizeof(saddr);
|
||||
if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) {
|
||||
/* Socket is already connected. */
|
||||
uv_connection_init((uv_stream_t*) handle);
|
||||
handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,7 @@ int uv_thread_join(uv_thread_t *tid) {
|
||||
else {
|
||||
CloseHandle(*tid);
|
||||
*tid = 0;
|
||||
MemoryBarrier(); /* For feature parity with pthread_join(). */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -198,6 +199,11 @@ int uv_mutex_init(uv_mutex_t* mutex) {
|
||||
}
|
||||
|
||||
|
||||
int uv_mutex_init_recursive(uv_mutex_t* mutex) {
|
||||
return uv_mutex_init(mutex);
|
||||
}
|
||||
|
||||
|
||||
void uv_mutex_destroy(uv_mutex_t* mutex) {
|
||||
DeleteCriticalSection(mutex);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
|
||||
}
|
||||
|
||||
|
||||
RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare);
|
||||
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) {
|
||||
|
@ -112,14 +112,30 @@ static int uv_tty_virtual_offset = -1;
|
||||
static int uv_tty_virtual_height = -1;
|
||||
static int uv_tty_virtual_width = -1;
|
||||
|
||||
/* The console window size
|
||||
* We keep this separate from uv_tty_virtual_*. We use those values to only
|
||||
* handle signalling SIGWINCH
|
||||
*/
|
||||
|
||||
static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE;
|
||||
static int uv__tty_console_height = -1;
|
||||
static int uv__tty_console_width = -1;
|
||||
|
||||
static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param);
|
||||
static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,
|
||||
DWORD event,
|
||||
HWND hwnd,
|
||||
LONG idObject,
|
||||
LONG idChild,
|
||||
DWORD dwEventThread,
|
||||
DWORD dwmsEventTime);
|
||||
|
||||
/* We use a semaphore rather than a mutex or critical section because in some
|
||||
cases (uv__cancel_read_console) we need take the lock in the main thread and
|
||||
release it in another thread. Using a semaphore ensures that in such
|
||||
scenario the main thread will still block when trying to acquire the lock. */
|
||||
static uv_sem_t uv_tty_output_lock;
|
||||
|
||||
static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
static WORD uv_tty_default_text_attributes =
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
|
||||
@ -141,6 +157,18 @@ static void uv__determine_vterm_state(HANDLE handle);
|
||||
void uv_console_init(void) {
|
||||
if (uv_sem_init(&uv_tty_output_lock, 1))
|
||||
abort();
|
||||
uv__tty_console_handle = CreateFileW(L"CONOUT$",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
0);
|
||||
if (uv__tty_console_handle != NULL) {
|
||||
QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
|
||||
NULL,
|
||||
WT_EXECUTELONGFUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -148,6 +176,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
||||
HANDLE handle;
|
||||
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
|
||||
|
||||
uv__once_init();
|
||||
handle = (HANDLE) uv__get_osfhandle(fd);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return UV_EBADF;
|
||||
@ -183,11 +212,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
|
||||
if (uv__vterm_state == UV_UNCHECKED)
|
||||
uv__determine_vterm_state(handle);
|
||||
|
||||
/* Store the global tty output handle. This handle is used by TTY read */
|
||||
/* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */
|
||||
/* is received. */
|
||||
uv_tty_output_handle = handle;
|
||||
|
||||
/* Remember the original console text attributes. */
|
||||
uv_tty_capture_initial_style(&screen_buffer_info);
|
||||
|
||||
@ -704,25 +728,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
|
||||
}
|
||||
records_left--;
|
||||
|
||||
/* If the window was resized, recompute the virtual window size. This */
|
||||
/* will trigger a SIGWINCH signal if the window size changed in an */
|
||||
/* way that matters to libuv. */
|
||||
if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
|
||||
uv_sem_wait(&uv_tty_output_lock);
|
||||
|
||||
if (uv_tty_output_handle != INVALID_HANDLE_VALUE &&
|
||||
GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) {
|
||||
uv_tty_update_virtual_window(&info);
|
||||
}
|
||||
|
||||
uv_sem_post(&uv_tty_output_lock);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore other events that are not key or resize events. */
|
||||
/* Ignore other events that are not key events. */
|
||||
if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) {
|
||||
continue;
|
||||
}
|
||||
@ -1102,9 +1108,6 @@ static int uv__cancel_read_console(uv_tty_t* handle) {
|
||||
|
||||
|
||||
static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
|
||||
int old_virtual_width = uv_tty_virtual_width;
|
||||
int old_virtual_height = uv_tty_virtual_height;
|
||||
|
||||
uv_tty_virtual_width = info->dwSize.X;
|
||||
uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
|
||||
|
||||
@ -1124,14 +1127,6 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
|
||||
if (uv_tty_virtual_offset < 0) {
|
||||
uv_tty_virtual_offset = 0;
|
||||
}
|
||||
|
||||
/* If the virtual window size changed, emit a SIGWINCH signal. Don't emit */
|
||||
/* if this was the first time the virtual window size was computed. */
|
||||
if (old_virtual_width != -1 && old_virtual_height != -1 &&
|
||||
(uv_tty_virtual_width != old_virtual_width ||
|
||||
uv_tty_virtual_height != old_virtual_height)) {
|
||||
uv__signal_dispatch(SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2279,3 +2274,55 @@ static void uv__determine_vterm_state(HANDLE handle) {
|
||||
|
||||
uv__vterm_state = UV_SUPPORTED;
|
||||
}
|
||||
|
||||
static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO sb_info;
|
||||
MSG msg;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
|
||||
return 0;
|
||||
|
||||
uv__tty_console_width = sb_info.dwSize.X;
|
||||
uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
|
||||
|
||||
if (pSetWinEventHook == NULL)
|
||||
return 0;
|
||||
|
||||
if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT,
|
||||
EVENT_CONSOLE_LAYOUT,
|
||||
NULL,
|
||||
uv__tty_console_resize_event,
|
||||
0,
|
||||
0,
|
||||
WINEVENT_OUTOFCONTEXT))
|
||||
return 0;
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,
|
||||
DWORD event,
|
||||
HWND hwnd,
|
||||
LONG idObject,
|
||||
LONG idChild,
|
||||
DWORD dwEventThread,
|
||||
DWORD dwmsEventTime) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO sb_info;
|
||||
int width, height;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
|
||||
return;
|
||||
|
||||
width = sb_info.dwSize.X;
|
||||
height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
|
||||
|
||||
if (width != uv__tty_console_width || height != uv__tty_console_height) {
|
||||
uv__tty_console_width = width;
|
||||
uv__tty_console_height = height;
|
||||
uv__signal_dispatch(SIGWINCH);
|
||||
}
|
||||
}
|
||||
|
@ -897,13 +897,12 @@ int uv__udp_send(uv_udp_send_t* req,
|
||||
int err;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
if (addrlen == sizeof(uv_addr_ip4_any_)) {
|
||||
if (addrlen == sizeof(uv_addr_ip4_any_))
|
||||
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
|
||||
} else if (addrlen == sizeof(uv_addr_ip6_any_)) {
|
||||
else if (addrlen == sizeof(uv_addr_ip6_any_))
|
||||
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
else
|
||||
return UV_EINVAL;
|
||||
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
@ -922,5 +921,45 @@ int uv__udp_try_send(uv_udp_t* handle,
|
||||
unsigned int nbufs,
|
||||
const struct sockaddr* addr,
|
||||
unsigned int addrlen) {
|
||||
return UV_ENOSYS;
|
||||
DWORD bytes;
|
||||
const struct sockaddr* bind_addr;
|
||||
struct sockaddr_storage converted;
|
||||
int err;
|
||||
|
||||
assert(nbufs > 0);
|
||||
|
||||
err = uv__convert_to_localhost_if_unspecified(addr, &converted);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Already sending a message.*/
|
||||
if (handle->send_queue_count != 0)
|
||||
return UV_EAGAIN;
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
if (addrlen == sizeof(uv_addr_ip4_any_))
|
||||
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
|
||||
else if (addrlen == sizeof(uv_addr_ip6_any_))
|
||||
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
|
||||
else
|
||||
return UV_EINVAL;
|
||||
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
|
||||
if (err)
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
err = WSASendTo(handle->socket,
|
||||
(WSABUF*)bufs,
|
||||
nbufs,
|
||||
&bytes,
|
||||
0,
|
||||
(const struct sockaddr*) &converted,
|
||||
addrlen,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (err)
|
||||
return uv_translate_sys_error(WSAGetLastError());
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
@ -331,7 +331,12 @@ uint64_t uv_get_total_memory(void) {
|
||||
}
|
||||
|
||||
|
||||
int uv_parent_pid(void) {
|
||||
uv_pid_t uv_os_getpid(void) {
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
|
||||
|
||||
uv_pid_t uv_os_getppid(void) {
|
||||
int parent_pid = -1;
|
||||
HANDLE handle;
|
||||
PROCESSENTRY32 pe;
|
||||
@ -1388,7 +1393,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
|
||||
return uv_translate_sys_error(GetLastError());
|
||||
|
||||
bufsize = sizeof(path);
|
||||
bufsize = ARRAY_SIZE(path);
|
||||
if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
|
||||
r = GetLastError();
|
||||
CloseHandle(token);
|
||||
@ -1403,7 +1408,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
|
||||
CloseHandle(token);
|
||||
|
||||
/* Get the username using GetUserNameW() */
|
||||
bufsize = sizeof(username);
|
||||
bufsize = ARRAY_SIZE(username);
|
||||
if (!GetUserNameW(username, &bufsize)) {
|
||||
r = GetLastError();
|
||||
|
||||
|
@ -52,11 +52,15 @@ sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
||||
/* Powrprof.dll function pointer */
|
||||
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||
|
||||
/* User32.dll function pointer */
|
||||
sSetWinEventHook pSetWinEventHook;
|
||||
|
||||
|
||||
void uv_winapi_init(void) {
|
||||
HMODULE ntdll_module;
|
||||
HMODULE kernel32_module;
|
||||
HMODULE powrprof_module;
|
||||
HMODULE user32_module;
|
||||
|
||||
ntdll_module = GetModuleHandleA("ntdll.dll");
|
||||
if (ntdll_module == NULL) {
|
||||
@ -156,4 +160,10 @@ void uv_winapi_init(void) {
|
||||
GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification");
|
||||
}
|
||||
|
||||
user32_module = LoadLibraryA("user32.dll");
|
||||
if (user32_module != NULL) {
|
||||
pSetWinEventHook = (sSetWinEventHook)
|
||||
GetProcAddress(user32_module, "SetWinEventHook");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4104,6 +4104,10 @@
|
||||
# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000
|
||||
#endif
|
||||
|
||||
#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
|
||||
# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002
|
||||
#endif
|
||||
|
||||
/* from winternl.h */
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
@ -4730,6 +4734,25 @@ typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification)
|
||||
HANDLE Recipient,
|
||||
_PHPOWERNOTIFY RegistrationHandle);
|
||||
|
||||
/* from Winuser.h */
|
||||
typedef VOID (CALLBACK* WINEVENTPROC)
|
||||
(HWINEVENTHOOK hWinEventHook,
|
||||
DWORD event,
|
||||
HWND hwnd,
|
||||
LONG idObject,
|
||||
LONG idChild,
|
||||
DWORD idEventThread,
|
||||
DWORD dwmsEventTime);
|
||||
|
||||
typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
|
||||
(UINT eventMin,
|
||||
UINT eventMax,
|
||||
HMODULE hmodWinEventProc,
|
||||
WINEVENTPROC lpfnWinEventProc,
|
||||
DWORD idProcess,
|
||||
DWORD idThread,
|
||||
UINT dwflags);
|
||||
|
||||
|
||||
/* Ntdll function pointers */
|
||||
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
|
||||
@ -4758,4 +4781,7 @@ extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
|
||||
/* Powrprof.dll function pointer */
|
||||
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
|
||||
|
||||
/* User32.dll function pointer */
|
||||
extern sSetWinEventHook pSetWinEventHook;
|
||||
|
||||
#endif /* UV_WIN_WINAPI_H_ */
|
||||
|
@ -559,3 +559,31 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
|
||||
struct sockaddr_storage* storage) {
|
||||
struct sockaddr_in* dest4;
|
||||
struct sockaddr_in6* dest6;
|
||||
|
||||
if (addr == NULL)
|
||||
return UV_EINVAL;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
dest4 = (struct sockaddr_in*) storage;
|
||||
memcpy(dest4, addr, sizeof(*dest4));
|
||||
if (dest4->sin_addr.s_addr == 0)
|
||||
dest4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
return 0;
|
||||
case AF_INET6:
|
||||
dest6 = (struct sockaddr_in6*) storage;
|
||||
memcpy(dest6, addr, sizeof(*dest6));
|
||||
if (memcmp(&dest6->sin6_addr,
|
||||
&uv_addr_ip6_any_.sin6_addr,
|
||||
sizeof(uv_addr_ip6_any_.sin6_addr)) == 0)
|
||||
dest6->sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
|
||||
return 0;
|
||||
default:
|
||||
return UV_EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -188,4 +188,7 @@ typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH {
|
||||
|
||||
#endif
|
||||
|
||||
int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
|
||||
struct sockaddr_storage* storage);
|
||||
|
||||
#endif /* UV_WIN_WINSOCK_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user