Codebase list libuv1 / 74b6422
Merge tag 'upstream/1.8.0' into debian/sid Upstream version 1.8.0 Luca Bruno 8 years ago
74 changed file(s) with 1483 addition(s) and 378 deletion(s). Raw diff Collapse all Expand all
2121 Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
2222 Michael <michael_dawson@ca.ibm.com>
2323 Michael Neumann <mneumann@think.localnet> <mneumann@ntecs.de>
24 Nicholas Vavilov <vvnicholas@gmail.com>
2425 Rasmus Christian Pedersen <zerhacken@yahoo.com>
2526 Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
2627 Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
224224 Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
225225 Eli Skeggs <skeggse@gmail.com>
226226 nmushell <nmushell@bloomberg.net>
227 Gireesh Punathil <gpunathi@in.ibm.com>
228 Ryan Johnston <ryan@mediapixel.co.nz>
229 Adam Stylinski <stylinae@mail.uc.edu>
230 Nathan Corvino <nathan@corvino.com>
231 Wink Saville <wink@saville.com>
232 Angel Leon <gubatron@gmail.com>
233 Louis DeJardin <lodejard@microsoft.com>
234 Imran Iqbal <imrani@ca.ibm.com>
235 Petka Antonov <petka_antonov@hotmail.com>
236 Ian Kronquist <iankronquist@teleport.com>
237 kkdaemon <kkdaemon@gmail.com>
238 Yuval Brik <yuval@brik.org.il>
239 Joran Dirk Greef <joran@ronomon.com>
240 Andrey Mazo <andrey.mazo@fidelissecurity.com>
241 sztomi <hello.sztomi@gmail.com>
0 2015.09.23, Version 1.7.5 (Stable)
0 2015.12.15, Version 1.8.0 (Stable)
1
2 Changes since version 1.7.5:
3
4 * unix: fix memory leak in uv_interface_addresses (Jianghua Yang)
5
6 * unix: make uv_guess_handle work properly for AIX (Gireesh Punathil)
7
8 * fs: undo uv__req_init when uv__malloc failed (Jianghua Yang)
9
10 * build: remove unused 'component' GYP option (Saúl Ibarra Corretgé)
11
12 * include: remove duplicate extern declaration (Jianghua Yang)
13
14 * win: use the MSVC provided snprintf where possible (Jason Williams)
15
16 * win, test: fix compilation warning (Saúl Ibarra Corretgé)
17
18 * win: fix compilation with VS < 2012 (Ryan Johnston)
19
20 * stream: support empty uv_try_write on unix (Fedor Indutny)
21
22 * unix: fix request handle leak in uv__udp_send (Jianghua Yang)
23
24 * src: replace QUEUE_SPLIT with QUEUE_MOVE (Ben Noordhuis)
25
26 * unix: use QUEUE_MOVE when iterating over lists (Ben Noordhuis)
27
28 * unix: squelch harmless valgrind warning (Ben Noordhuis)
29
30 * test: don't abort on setrlimit() failure (Ben Noordhuis)
31
32 * unix: only undo fs req registration in async mode (Ben Noordhuis)
33
34 * unix: fix uv__getiovmax return value (HungMingWu)
35
36 * unix: make work with Solaris Studio. (Adam Stylinski)
37
38 * test: fix fs_event_watch_file_currentdir flakiness (Santiago Gimeno)
39
40 * unix: skip prohibited syscalls on tvOS and watchOS (Nathan Corvino)
41
42 * test: use FQDN in getaddrinfo_fail test (Wink Saville)
43
44 * docs: clarify documentation of uv_tcp_init_ex (Andrius Bentkus)
45
46 * win: fix comment (Miodrag Milanovic)
47
48 * doc: fix typo in README (Angel Leon)
49
50 * darwin: abort() if (un)locking fs mutex fails (Ben Noordhuis)
51
52 * pipe: enable inprocess uv_write2 on Windows (Louis DeJardin)
53
54 * win: properly return UV_EBADF when _close() fails (Nicholas Vavilov)
55
56 * test: skip process_title for AIX (Imran Iqbal)
57
58 * misc: expose handle print APIs (Petka Antonov)
59
60 * include: add stdio.h to uv.h (Saúl Ibarra Corretgé)
61
62 * misc: remove unnecessary null pointer checks (Ian Kronquist)
63
64 * test,freebsd: skip udp_dual_stack if not supported (Santiago Gimeno)
65
66 * linux: don't retry dup2/dup3 on EINTR (Ben Noordhuis)
67
68 * unix: don't retry dup2/dup3 on EINTR (Ben Noordhuis)
69
70 * test: fix -Wtautological-pointer-compare warnings (Saúl Ibarra Corretgé)
71
72 * win: map ERROR_BAD_PATHNAME to UV_ENOENT (Tony Kelman)
73
74 * test: fix test/test-tty.c for AIX (Imran Iqbal)
75
76 * android: support api level less than 21 (kkdaemon)
77
78 * fsevents: fix race on simultaneous init+close (Fedor Indutny)
79
80 * linux,fs: fix p{read,write}v with a 64bit offset (Saúl Ibarra Corretgé)
81
82 * fs: add uv_fs_realpath() (Yuval Brik)
83
84 * win: fix path for removed and renamed fs events (Joran Dirk Greef)
85
86 * win: do not read more from stream than available (Jeremy Whitlock)
87
88 * test: test that uv_close() doesn't corrupt QUEUE (Andrey Mazo)
89
90 * unix: fix uv_fs_event_stop() from fs_event_cb (Andrey Mazo)
91
92 * test: fix self-deadlocks in thread_rwlock_trylock (Ben Noordhuis)
93
94 * src: remove non ascii character (sztomi)
95
96 * test: fix test udp_multicast_join6 for AIX (Imran Iqbal)
97
98
99 2015.09.23, Version 1.7.5 (Stable), a8c1136de2cabf25b143021488cbaab05834daa8
1100
2101 Changes since version 1.7.4:
3102
199199 test/test-poll-closesocket.c \
200200 test/test-poll.c \
201201 test/test-process-title.c \
202 test/test-queue-foreach-delete.c \
202203 test/test-ref.c \
203204 test/test-run-nowait.c \
204205 test/test-run-once.c \
118118 $ git verify-tag v1.6.1
119119
120120 Starting with libuv 1.7.0, the tarballs stored in the
121 [downloads site](http://dist.libuv.org/dist/) are signed and an accomanying
121 [downloads site](http://dist.libuv.org/dist/) are signed and an accompanying
122122 signature file sit alongside each. Once both the release tarball and the
123123 signature file are downloaded, the file can be verified as follows:
124124
0 version: v1.7.5.build{build}
0 version: v1.8.0.build{build}
11
22 install:
33 - cinst -y nsis
33 'target_arch%': 'ia32', # set v8's target architecture
44 'host_arch%': 'ia32', # set v8's host architecture
55 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
6 'component%': 'static_library', # NB. these names match with what V8 expects
76 'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
87 },
98
1212 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1313
1414 AC_PREREQ(2.57)
15 AC_INIT([libuv], [1.7.5], [https://github.com/libuv/libuv/issues])
15 AC_INIT([libuv], [1.8.0], [https://github.com/libuv/libuv/issues])
1616 AC_CONFIG_MACRO_DIR([m4])
1717 m4_include([m4/libuv-extra-automake-flags.m4])
1818 m4_include([m4/as_case.m4])
278278
279279 Equivalent to :man:`readlink(2)`.
280280
281 .. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
282
283 Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``.
284
285 .. note::
286 This function is not implemented on Windows XP and Windows Server 2003.
287 On these systems, UV_ENOSYS is returned.
288
289 .. versionadded:: 1.8.0
290
281291 .. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
282292 .. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
283293
287287 .. note::
288288 Not every platform can support nanosecond resolution; however, this value will always
289289 be in nanoseconds.
290
291 .. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
292
293 Prints all handles associated with the given `loop` to the given `stream`.
294
295 Example:
296
297 ::
298
299 uv_print_all_handles(uv_default_loop(), stderr);
300 /*
301 [--I] signal 0x1a25ea8
302 [-AI] async 0x1a25cf0
303 [R--] idle 0x1a7a8c8
304 */
305
306 The format is `[flags] handle-type handle-address`. For `flags`:
307
308 - `R` is printed for a handle that is referenced
309 - `A` is printed for a handle that is active
310 - `I` is printed for a handle that is internal
311
312 .. warning::
313 This function is meant for ad hoc debugging, there is no API/ABI
314 stability guarantees.
315
316 .. versionadded:: 1.8.0
317
318 .. c:function:: void uv_print_active_handles(uv_loop_t* loop, FILE* stream)
319
320 This is the same as :c:func:`uv_print_all_handles` except only active handles
321 are printed.
322
323 .. warning::
324 This function is meant for ad hoc debugging, there is no API/ABI
325 stability guarantees.
326
327 .. versionadded:: 1.8.0
3333
3434 .. c:function:: int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags)
3535
36 Initialize the handle with the specified flags. At the moment the lower 8 bits
36 Initialize the handle with the specified flags. At the moment only the lower 8 bits
3737 of the `flags` parameter are used as the socket domain. A socket will be created
3838 for the given domain. If the specified domain is ``AF_UNSPEC`` no socket is created,
3939 just like :c:func:`uv_tcp_init`.
8282 if not any(a.startswith('-Duv_library=') for a in args):
8383 args.append('-Duv_library=static_library')
8484
85 if not any(a.startswith('-Dcomponent=') for a in args):
86 args.append('-Dcomponent=static_library')
87
8885 # Some platforms (OpenBSD for example) don't have multiprocessing.synchronize
8986 # so gyp must be run with --no-parallel
9087 if not gyp_parallel_support:
3030 */
3131
3232 #define UV_VERSION_MAJOR 1
33 #define UV_VERSION_MINOR 7
34 #define UV_VERSION_PATCH 5
33 #define UV_VERSION_MINOR 8
34 #define UV_VERSION_PATCH 0
3535 #define UV_VERSION_IS_RELEASE 1
3636 #define UV_VERSION_SUFFIX ""
3737
4747 #include "uv-errno.h"
4848 #include "uv-version.h"
4949 #include <stddef.h>
50 #include <stdio.h>
5051
5152 #if defined(_MSC_VER) && _MSC_VER < 1600
5253 # include "stdint-msvc2008.h"
423424
424425 UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
425426
427 /* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */
428 UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream);
429 UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream);
430
426431 UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
427432
428433 UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value);
10821087 UV_FS_SYMLINK,
10831088 UV_FS_READLINK,
10841089 UV_FS_CHOWN,
1085 UV_FS_FCHOWN
1090 UV_FS_FCHOWN,
1091 UV_FS_REALPATH
10861092 } uv_fs_type;
10871093
10881094 /* uv_fs_t is a subclass of uv_req_t. */
12341240 uv_fs_t* req,
12351241 const char* path,
12361242 uv_fs_cb cb);
1243 UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,
1244 uv_fs_t* req,
1245 const char* path,
1246 uv_fs_cb cb);
12371247 UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
12381248 uv_fs_t* req,
12391249 uv_file file,
13621372 UV_EXTERN uint64_t uv_get_free_memory(void);
13631373 UV_EXTERN uint64_t uv_get_total_memory(void);
13641374
1365 UV_EXTERN extern uint64_t uv_hrtime(void);
1375 UV_EXTERN uint64_t uv_hrtime(void);
13661376
13671377 UV_EXTERN void uv_disable_stdio_inheritance(void);
13681378
5454 char tmp[UV__INET_ADDRSTRLEN];
5555 int l;
5656
57 #ifndef _WIN32
5857 l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
59 #else
60 l = _snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
61 #endif
6258 if (l <= 0 || (size_t) l >= size) {
6359 return UV_ENOSPC;
6460 }
2929 #define QUEUE_DATA(ptr, type, field) \
3030 ((type *) ((char *) (ptr) - offsetof(type, field)))
3131
32 /* Important note: mutating the list while QUEUE_FOREACH is
33 * iterating over its elements results in undefined behavior.
34 */
3235 #define QUEUE_FOREACH(q, h) \
3336 for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
3437
6568 } \
6669 while (0)
6770
71 #define QUEUE_MOVE(h, n) \
72 do { \
73 if (QUEUE_EMPTY(h)) \
74 QUEUE_INIT(n); \
75 else { \
76 QUEUE* q = QUEUE_HEAD(h); \
77 QUEUE_SPLIT(h, q, n); \
78 } \
79 } \
80 while (0)
81
6882 #define QUEUE_INSERT_HEAD(h, q) \
6983 do { \
7084 QUEUE_NEXT(q) = QUEUE_NEXT(h); \
222222 int err;
223223
224224 loop = container_of(handle, uv_loop_t, wq_async);
225 QUEUE_INIT(&wq);
226
227225 uv_mutex_lock(&loop->wq_mutex);
228 if (!QUEUE_EMPTY(&loop->wq)) {
229 q = QUEUE_HEAD(&loop->wq);
230 QUEUE_SPLIT(&loop->wq, q, &wq);
231 }
226 QUEUE_MOVE(&loop->wq, &wq);
232227 uv_mutex_unlock(&loop->wq_mutex);
233228
234229 while (!QUEUE_EMPTY(&wq)) {
00 /*
11 Copyright (c) 2013, Kenneth MacKay
2 Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement n° 289016)
2 Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016)
33 All rights reserved.
44
55 Redistribution and use in source and binary forms, with or without modification,
7777 static void uv__async_event(uv_loop_t* loop,
7878 struct uv__async* w,
7979 unsigned int nevents) {
80 QUEUE queue;
8081 QUEUE* q;
8182 uv_async_t* h;
8283
83 QUEUE_FOREACH(q, &loop->async_handles) {
84 QUEUE_MOVE(&loop->async_handles, &queue);
85 while (!QUEUE_EMPTY(&queue)) {
86 q = QUEUE_HEAD(&queue);
8487 h = QUEUE_DATA(q, uv_async_t, queue);
88
89 QUEUE_REMOVE(q);
90 QUEUE_INSERT_TAIL(&loop->async_handles, q);
8591
8692 if (cmpxchgi(&h->pending, 1, 0) == 0)
8793 continue;
1616 #define UV_ATOMIC_OPS_H_
1717
1818 #include "internal.h" /* UV_UNUSED */
19
20 #if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
21 #include <atomic.h>
22 #define __sync_val_compare_and_swap(p, o, n) atomic_cas_ptr(p, o, n)
23 #endif
1924
2025 UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
2126 UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval));
7474 #include <sys/ioctl.h>
7575 #endif
7676
77 #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
78 # include <dlfcn.h> /* for dlsym */
79 #endif
80
7781 static int uv__run_pending(uv_loop_t* loop);
7882
7983 /* Verify that uv_buf_t is ABI-compatible with struct iovec. */
203207 return IOV_MAX;
204208 #elif defined(_SC_IOV_MAX)
205209 static int iovmax = -1;
206 if (iovmax == -1)
210 if (iovmax == -1) {
207211 iovmax = sysconf(_SC_IOV_MAX);
212 /* On some embedded devices (arm-linux-uclibc based ip camera),
213 * sysconf(_SC_IOV_MAX) can not get the correct value. The return
214 * value is -1 and the errno is EINPROGRESS. Degrade the value to 1.
215 */
216 if (iovmax == -1) iovmax = 1;
217 }
208218 return iovmax;
209219 #else
210220 return 1024;
720730 if (QUEUE_EMPTY(&loop->pending_queue))
721731 return 0;
722732
723 QUEUE_INIT(&pq);
724 q = QUEUE_HEAD(&loop->pending_queue);
725 QUEUE_SPLIT(&loop->pending_queue, q, &pq);
733 QUEUE_MOVE(&loop->pending_queue, &pq);
726734
727735 while (!QUEUE_EMPTY(&pq)) {
728736 q = QUEUE_HEAD(&pq);
955963 int uv__dup2_cloexec(int oldfd, int newfd) {
956964 int r;
957965 #if defined(__FreeBSD__) && __FreeBSD__ >= 10
958 do
959 r = dup3(oldfd, newfd, O_CLOEXEC);
960 while (r == -1 && errno == EINTR);
966 r = dup3(oldfd, newfd, O_CLOEXEC);
961967 if (r == -1)
962968 return -errno;
963969 return r;
964970 #elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
965 do
966 r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
967 while (r == -1 && errno == EINTR);
971 r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
968972 if (r != -1)
969973 return r;
970974 if (errno != EINVAL)
975979 if (!no_dup3) {
976980 do
977981 r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
978 while (r == -1 && (errno == EINTR || errno == EBUSY));
982 while (r == -1 && errno == EBUSY);
979983 if (r != -1)
980984 return r;
981985 if (errno != ENOSYS)
989993 do
990994 r = dup2(oldfd, newfd);
991995 #if defined(__linux__)
992 while (r == -1 && (errno == EINTR || errno == EBUSY));
996 while (r == -1 && errno == EBUSY);
993997 #else
994 while (r == -1 && errno == EINTR);
998 while (0); /* Never retry. */
995999 #endif
9961000
9971001 if (r == -1)
10171021 size_t len;
10181022 long initsize;
10191023 int r;
1024 #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
1025 int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
1026 #endif
10201027
10211028 if (buffer == NULL || size == NULL || *size == 0)
10221029 return -EINVAL;
10381045 return 0;
10391046 }
10401047
1048 #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
1049 getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
1050 if (getpwuid_r == NULL)
1051 return -ENOSYS;
1052 #endif
1053
10411054 /* HOME is not set, so call getpwuid() */
10421055 initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
10431056
257257 }
258258
259259 *addresses = uv__malloc(*count * sizeof(**addresses));
260 if (!(*addresses))
260 if (!(*addresses)) {
261 freeifaddrs(addrs);
261262 return -ENOMEM;
263 }
262264
263265 address = *addresses;
264266
3838
3939
4040 void uv_dlclose(uv_lib_t* lib) {
41 if (lib->errmsg) {
42 uv__free(lib->errmsg);
43 lib->errmsg = NULL;
44 }
41 uv__free(lib->errmsg);
42 lib->errmsg = NULL;
4543
4644 if (lib->handle) {
4745 /* Ignore errors. No good way to signal them without leaking memory. */
6664 static int uv__dlerror(uv_lib_t* lib) {
6765 const char* errmsg;
6866
69 if (lib->errmsg)
70 uv__free(lib->errmsg);
67 uv__free(lib->errmsg);
7168
7269 errmsg = dlerror();
7370
175175 int uv_set_process_title(const char* title) {
176176 int oid[4];
177177
178 if (process_title) uv__free(process_title);
178 uv__free(process_title);
179179 process_title = uv__strdup(title);
180180
181181 oid[0] = CTL_KERN;
372372 }
373373
374374 *addresses = uv__malloc(*count * sizeof(**addresses));
375 if (!(*addresses))
375 if (!(*addresses)) {
376 freeifaddrs(addrs);
376377 return -ENOMEM;
378 }
377379
378380 address = *addresses;
379381
7979 req->path = path; \
8080 } else { \
8181 req->path = uv__strdup(path); \
82 if (req->path == NULL) \
82 if (req->path == NULL) { \
83 uv__req_unregister(loop, req); \
8384 return -ENOMEM; \
85 } \
8486 } \
8587 } \
8688 while (0)
9698 path_len = strlen(path) + 1; \
9799 new_path_len = strlen(new_path) + 1; \
98100 req->path = uv__malloc(path_len + new_path_len); \
99 if (req->path == NULL) \
101 if (req->path == NULL) { \
102 uv__req_unregister(loop, req); \
100103 return -ENOMEM; \
104 } \
101105 req->new_path = req->path + path_len; \
102106 memcpy((void*) req->path, path, path_len); \
103107 memcpy((void*) req->new_path, new_path, new_path_len); \
369373 }
370374
371375
376 static ssize_t uv__fs_pathmax_size(const char* path) {
377 ssize_t pathmax;
378
379 pathmax = pathconf(path, _PC_PATH_MAX);
380
381 if (pathmax == -1) {
382 #if defined(PATH_MAX)
383 return PATH_MAX;
384 #else
385 return 4096;
386 #endif
387 }
388
389 return pathmax;
390 }
391
372392 static ssize_t uv__fs_readlink(uv_fs_t* req) {
373393 ssize_t len;
374394 char* buf;
375395
376 len = pathconf(req->path, _PC_PATH_MAX);
377
378 if (len == -1) {
379 #if defined(PATH_MAX)
380 len = PATH_MAX;
381 #else
382 len = 4096;
383 #endif
384 }
385
396 len = uv__fs_pathmax_size(req->path);
386397 buf = uv__malloc(len + 1);
387398
388399 if (buf == NULL) {
403414 return 0;
404415 }
405416
417 static ssize_t uv__fs_realpath(uv_fs_t* req) {
418 ssize_t len;
419 char* buf;
420
421 len = uv__fs_pathmax_size(req->path);
422 buf = uv__malloc(len + 1);
423
424 if (buf == NULL) {
425 errno = ENOMEM;
426 return -1;
427 }
428
429 if (realpath(req->path, buf) == NULL) {
430 uv__free(buf);
431 return -1;
432 }
433
434 req->ptr = buf;
435
436 return 0;
437 }
406438
407439 static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
408440 struct pollfd pfd;
625657 */
626658 #if defined(__APPLE__)
627659 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
628 pthread_mutex_lock(&lock);
660
661 if (pthread_mutex_lock(&lock))
662 abort();
629663 #endif
630664
631665 if (req->off < 0) {
682716
683717 done:
684718 #if defined(__APPLE__)
685 pthread_mutex_unlock(&lock);
719 if (pthread_mutex_unlock(&lock))
720 abort();
686721 #endif
687722
688723 return r;
866901 X(READ, uv__fs_buf_iter(req, uv__fs_read));
867902 X(SCANDIR, uv__fs_scandir(req));
868903 X(READLINK, uv__fs_readlink(req));
904 X(REALPATH, uv__fs_realpath(req));
869905 X(RENAME, rename(req->path, req->new_path));
870906 X(RMDIR, rmdir(req->path));
871907 X(SENDFILE, uv__fs_sendfile(req));
10611097 uv_fs_cb cb) {
10621098 INIT(MKDTEMP);
10631099 req->path = uv__strdup(tpl);
1064 if (req->path == NULL)
1100 if (req->path == NULL) {
1101 if (cb != NULL)
1102 uv__req_unregister(loop, req);
10651103 return -ENOMEM;
1104 }
10661105 POST;
10671106 }
10681107
10981137 if (nbufs > ARRAY_SIZE(req->bufsml))
10991138 req->bufs = uv__malloc(nbufs * sizeof(*bufs));
11001139
1101 if (req->bufs == NULL)
1140 if (req->bufs == NULL) {
1141 if (cb != NULL)
1142 uv__req_unregister(loop, req);
11021143 return -ENOMEM;
1144 }
11031145
11041146 memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
11051147
11251167 const char* path,
11261168 uv_fs_cb cb) {
11271169 INIT(READLINK);
1170 PATH;
1171 POST;
1172 }
1173
1174
1175 int uv_fs_realpath(uv_loop_t* loop,
1176 uv_fs_t* req,
1177 const char * path,
1178 uv_fs_cb cb) {
1179 INIT(REALPATH);
11281180 PATH;
11291181 POST;
11301182 }
12231275 if (nbufs > ARRAY_SIZE(req->bufsml))
12241276 req->bufs = uv__malloc(nbufs * sizeof(*bufs));
12251277
1226 if (req->bufs == NULL)
1278 if (req->bufs == NULL) {
1279 if (cb != NULL)
1280 uv__req_unregister(loop, req);
12271281 return -ENOMEM;
1282 }
12281283
12291284 memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
12301285
7272 typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
7373 typedef struct uv__cf_loop_state_s uv__cf_loop_state_t;
7474
75 enum uv__cf_loop_signal_type_e {
76 kUVCFLoopSignalRegular,
77 kUVCFLoopSignalClosing
78 };
79 typedef enum uv__cf_loop_signal_type_e uv__cf_loop_signal_type_t;
80
7581 struct uv__cf_loop_signal_s {
7682 QUEUE member;
7783 uv_fs_event_t* handle;
84 uv__cf_loop_signal_type_t type;
7885 };
7986
8087 struct uv__fsevents_event_s {
97104 /* Forward declarations */
98105 static void uv__cf_loop_cb(void* arg);
99106 static void* uv__cf_loop_runner(void* arg);
100 static int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle);
107 static int uv__cf_loop_signal(uv_loop_t* loop,
108 uv_fs_event_t* handle,
109 uv__cf_loop_signal_type_t type);
101110
102111 /* Lazy-loaded by uv__fsevents_global_init(). */
103112 static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef,
148157 int err; \
149158 uv_mutex_lock(&(handle)->cf_mutex); \
150159 /* Split-off all events and empty original queue */ \
151 QUEUE_INIT(&events); \
152 if (!QUEUE_EMPTY(&(handle)->cf_events)) { \
153 q = QUEUE_HEAD(&(handle)->cf_events); \
154 QUEUE_SPLIT(&(handle)->cf_events, q, &events); \
155 } \
160 QUEUE_MOVE(&(handle)->cf_events, &events); \
156161 /* Get error (if any) and zero original one */ \
157162 err = (handle)->cf_error; \
158163 (handle)->cf_error = 0; \
386391
387392
388393 /* Runs in CF thread, when there're new fsevent handles to add to stream */
389 static void uv__fsevents_reschedule(uv_fs_event_t* handle) {
394 static void uv__fsevents_reschedule(uv_fs_event_t* handle,
395 uv__cf_loop_signal_type_t type) {
390396 uv__cf_loop_state_t* state;
391397 QUEUE* q;
392398 uv_fs_event_t* curr;
485491 *
486492 * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close`
487493 */
488 if (!uv__is_active(handle))
494 if (type == kUVCFLoopSignalClosing)
489495 uv_sem_post(&state->fsevent_sem);
490496 }
491497
675681 if (loop->cf_state == NULL)
676682 return;
677683
678 if (uv__cf_loop_signal(loop, NULL) != 0)
684 if (uv__cf_loop_signal(loop, NULL, kUVCFLoopSignalRegular) != 0)
679685 abort();
680686
681687 uv_thread_join(&loop->cf_thread);
734740
735741 loop = arg;
736742 state = loop->cf_state;
737 QUEUE_INIT(&split_head);
738743
739744 uv_mutex_lock(&loop->cf_mutex);
740 if (!QUEUE_EMPTY(&loop->cf_signals)) {
741 QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals);
742 QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head);
743 }
745 QUEUE_MOVE(&loop->cf_signals, &split_head);
744746 uv_mutex_unlock(&loop->cf_mutex);
745747
746748 while (!QUEUE_EMPTY(&split_head)) {
747749 item = QUEUE_HEAD(&split_head);
750 QUEUE_REMOVE(item);
748751
749752 s = QUEUE_DATA(item, uv__cf_loop_signal_t, member);
750753
752755 if (s->handle == NULL)
753756 pCFRunLoopStop(state->loop);
754757 else
755 uv__fsevents_reschedule(s->handle);
756
757 QUEUE_REMOVE(item);
758 uv__fsevents_reschedule(s->handle, s->type);
759
758760 uv__free(s);
759761 }
760762 }
761763
762764
763765 /* Runs in UV loop to notify CF thread */
764 int uv__cf_loop_signal(uv_loop_t* loop, uv_fs_event_t* handle) {
766 int uv__cf_loop_signal(uv_loop_t* loop,
767 uv_fs_event_t* handle,
768 uv__cf_loop_signal_type_t type) {
765769 uv__cf_loop_signal_t* item;
766770 uv__cf_loop_state_t* state;
767771
770774 return -ENOMEM;
771775
772776 item->handle = handle;
777 item->type = type;
773778
774779 uv_mutex_lock(&loop->cf_mutex);
775780 QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member);
832837
833838 /* Reschedule FSEventStream */
834839 assert(handle != NULL);
835 err = uv__cf_loop_signal(handle->loop, handle);
840 err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalRegular);
836841 if (err)
837842 goto fail_loop_signal;
838843
872877
873878 /* Reschedule FSEventStream */
874879 assert(handle != NULL);
875 err = uv__cf_loop_signal(handle->loop, handle);
880 err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing);
876881 if (err)
877882 return -err;
878883
813813 return 0;
814814
815815 *addresses = uv__malloc(*count * sizeof(**addresses));
816 if (!(*addresses))
816 if (!(*addresses)) {
817 freeifaddrs(addrs);
817818 return -ENOMEM;
819 }
818820
819821 address = *addresses;
820822
3434 struct watcher_list {
3535 RB_ENTRY(watcher_list) entry;
3636 QUEUE watchers;
37 int iterating;
3738 char* path;
3839 int wd;
3940 };
112113 return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w);
113114 }
114115
116 static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
117 /* if the watcher_list->watchers is being iterated over, we can't free it. */
118 if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) {
119 /* No watchers left for this path. Clean up. */
120 RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w);
121 uv__inotify_rm_watch(loop->inotify_fd, w->wd);
122 uv__free(w);
123 }
124 }
115125
116126 static void uv__inotify_read(uv_loop_t* loop,
117127 uv__io_t* dummy,
119129 const struct uv__inotify_event* e;
120130 struct watcher_list* w;
121131 uv_fs_event_t* h;
132 QUEUE queue;
122133 QUEUE* q;
123134 const char* path;
124135 ssize_t size;
158169 */
159170 path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path);
160171
161 QUEUE_FOREACH(q, &w->watchers) {
172 /* We're about to iterate over the queue and call user's callbacks.
173 * What can go wrong?
174 * A callback could call uv_fs_event_stop()
175 * and the queue can change under our feet.
176 * So, we use QUEUE_MOVE() trick to safely iterate over the queue.
177 * And we don't free the watcher_list until we're done iterating.
178 *
179 * First,
180 * tell uv_fs_event_stop() (that could be called from a user's callback)
181 * not to free watcher_list.
182 */
183 w->iterating = 1;
184 QUEUE_MOVE(&w->watchers, &queue);
185 while (!QUEUE_EMPTY(&queue)) {
186 q = QUEUE_HEAD(&queue);
162187 h = QUEUE_DATA(q, uv_fs_event_t, watchers);
188
189 QUEUE_REMOVE(q);
190 QUEUE_INSERT_TAIL(&w->watchers, q);
191
163192 h->cb(h, path, events, 0);
164193 }
194 /* done iterating, time to (maybe) free empty watcher_list */
195 w->iterating = 0;
196 maybe_free_watcher_list(w, loop);
165197 }
166198 }
167199 }
213245 w->wd = wd;
214246 w->path = strcpy((char*)(w + 1), path);
215247 QUEUE_INIT(&w->watchers);
248 w->iterating = 0;
216249 RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w);
217250
218251 no_insert:
240273 uv__handle_stop(handle);
241274 QUEUE_REMOVE(&handle->watchers);
242275
243 if (QUEUE_EMPTY(&w->watchers)) {
244 /* No watchers left for this path. Clean up. */
245 RB_REMOVE(watcher_root, CAST(&handle->loop->inotify_watchers), w);
246 uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd);
247 uv__free(w);
248 }
276 maybe_free_watcher_list(w, handle->loop);
249277
250278 return 0;
251279 }
443443 }
444444
445445
446 ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
446 ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
447447 #if defined(__NR_preadv)
448 return syscall(__NR_preadv, fd, iov, iovcnt, offset);
449 #else
450 return errno = ENOSYS, -1;
451 #endif
452 }
453
454
455 ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
448 return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
449 #else
450 return errno = ENOSYS, -1;
451 #endif
452 }
453
454
455 ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
456456 #if defined(__NR_pwritev)
457 return syscall(__NR_pwritev, fd, iov, iovcnt, offset);
457 return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
458458 #else
459459 return errno = ENOSYS, -1;
460460 #endif
150150 const char* path,
151151 const struct timespec times[2],
152152 int flags);
153 ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
154 ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
153 ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
154 ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
155155 int uv__dup3(int oldfd, int newfd, int flags);
156156
157157 #endif /* UV_LINUX_SYSCALL_H_ */
4646 \
4747 void uv__run_##name(uv_loop_t* loop) { \
4848 uv_##name##_t* h; \
49 QUEUE queue; \
4950 QUEUE* q; \
50 QUEUE_FOREACH(q, &loop->name##_handles) { \
51 QUEUE_MOVE(&loop->name##_handles, &queue); \
52 while (!QUEUE_EMPTY(&queue)) { \
53 q = QUEUE_HEAD(&queue); \
5154 h = QUEUE_DATA(q, uv_##name##_t, queue); \
55 QUEUE_REMOVE(q); \
56 QUEUE_INSERT_TAIL(&loop->name##_handles, q); \
5257 h->name##_cb(h); \
5358 } \
5459 } \
297297
298298 *addresses = uv__malloc(*count * sizeof(**addresses));
299299
300 if (!(*addresses))
300 if (!(*addresses)) {
301 freeifaddrs(addrs);
301302 return -ENOMEM;
303 }
302304
303305 address = *addresses;
304306
160160
161161
162162 int uv_set_process_title(const char* title) {
163 if (process_title) uv__free(process_title);
163 uv__free(process_title);
164164 process_title = uv__strdup(title);
165165 setproctitle(title);
166166 return 0;
312312
313313 *addresses = uv__malloc(*count * sizeof(**addresses));
314314
315 if (!(*addresses))
315 if (!(*addresses)) {
316 freeifaddrs(addrs);
316317 return -ENOMEM;
318 }
317319
318320 address = *addresses;
319321
269269 }
270270
271271
272 #if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
273 /* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
274 * avoided. Since this isn't called on those targets, the function
275 * doesn't even need to be defined for them.
276 */
272277 static void uv__process_child_init(const uv_process_options_t* options,
273278 int stdio_count,
274279 int (*pipes)[2],
374379 uv__write_int(error_fd, -errno);
375380 _exit(127);
376381 }
382 #endif
377383
378384
379385 int uv_spawn(uv_loop_t* loop,
380386 uv_process_t* process,
381387 const uv_process_options_t* options) {
388 #if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
389 /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
390 return -ENOSYS;
391 #else
382392 int signal_pipe[2] = { -1, -1 };
383393 int (*pipes)[2];
384394 int stdio_count;
527537 }
528538
529539 return err;
540 #endif
530541 }
531542
532543
233233 /* Stop all the signal watchers that are still attached to this loop. This
234234 * ensures that the (shared) signal tree doesn't contain any invalid entries
235235 * entries, and that signal handlers are removed when appropriate.
236 * It's safe to use QUEUE_FOREACH here because the handles and the handle
237 * queue are not modified by uv__signal_stop().
236238 */
237239 QUEUE_FOREACH(q, &loop->handle_queue) {
238240 uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);
778778
779779 if (req->send_handle) {
780780 struct msghdr msg;
781 char scratch[64];
782781 struct cmsghdr *cmsg;
783782 int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
783 char scratch[64] = {0};
784784
785785 assert(fd_to_send >= 0);
786786
14701470 uv__stream_osx_interrupt_select(stream);
14711471 }
14721472
1473 if (written == 0)
1473 if (written == 0 && req_size != 0)
14741474 return -EAGAIN;
14751475 else
14761476 return written;
692692 }
693693
694694 *addresses = uv__malloc(*count * sizeof(**addresses));
695 if (!(*addresses))
695 if (!(*addresses)) {
696 freeifaddrs(addrs);
696697 return -ENOMEM;
698 }
697699
698700 address = *addresses;
699701
235235 return UV_UDP;
236236
237237 if (type == SOCK_STREAM) {
238 #if defined(_AIX)
239 /* on AIX the getsockname call returns an empty sa structure
240 * for sockets of type AF_UNIX. For all other types it will
241 * return a properly filled in structure.
242 */
243 if (len == 0)
244 return UV_NAMED_PIPE;
245 #endif /* defined(_AIX) */
246
238247 if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
239248 return UV_TCP;
240249 if (sa.sa_family == AF_UNIX)
409409 if (nbufs > ARRAY_SIZE(req->bufsml))
410410 req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
411411
412 if (req->bufs == NULL)
412 if (req->bufs == NULL) {
413 uv__req_unregister(handle->loop, req);
413414 return -ENOMEM;
415 }
414416
415417 memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
416418 handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs);
140140 char buf[32];
141141 char* copy;
142142
143 #ifndef _WIN32
144143 snprintf(buf, sizeof(buf), "Unknown system error %d", err);
145 #else
146 _snprintf(buf, sizeof(buf), "Unknown system error %d", err);
147 #endif
148144 copy = uv__strdup(buf);
149145
150146 return copy != NULL ? copy : "Unknown system error";
340336
341337
342338 void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
339 QUEUE queue;
343340 QUEUE* q;
344341 uv_handle_t* h;
345342
346 QUEUE_FOREACH(q, &loop->handle_queue) {
343 QUEUE_MOVE(&loop->handle_queue, &queue);
344 while (!QUEUE_EMPTY(&queue)) {
345 q = QUEUE_HEAD(&queue);
347346 h = QUEUE_DATA(q, uv_handle_t, handle_queue);
347
348 QUEUE_REMOVE(q);
349 QUEUE_INSERT_TAIL(&loop->handle_queue, q);
350
348351 if (h->flags & UV__HANDLE_INTERNAL) continue;
349352 walk_cb(h, arg);
350353 }
351354 }
352355
353356
354 #ifndef NDEBUG
355 static void uv__print_handles(uv_loop_t* loop, int only_active) {
357 static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
356358 const char* type;
357359 QUEUE* q;
358360 uv_handle_t* h;
373375 default: type = "<unknown>";
374376 }
375377
376 fprintf(stderr,
378 fprintf(stream,
377379 "[%c%c%c] %-8s %p\n",
378380 "R-"[!(h->flags & UV__HANDLE_REF)],
379381 "A-"[!(h->flags & UV__HANDLE_ACTIVE)],
384386 }
385387
386388
387 void uv_print_all_handles(uv_loop_t* loop) {
388 uv__print_handles(loop, 0);
389 }
390
391
392 void uv_print_active_handles(uv_loop_t* loop) {
393 uv__print_handles(loop, 1);
394 }
395 #endif
389 void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
390 uv__print_handles(loop, 0, stream);
391 }
392
393
394 void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
395 uv__print_handles(loop, 1, stream);
396 }
396397
397398
398399 void uv_ref(uv_handle_t* handle) {
4040 #include "tree.h"
4141 #include "queue.h"
4242
43 #if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
44 extern int snprintf(char*, size_t, const char*, ...);
45 #endif
46
4347 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
4448
4549 #define container_of(ptr, type, member) \
128128 case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH;
129129 case WSAENETUNREACH: return UV_ENETUNREACH;
130130 case WSAENOBUFS: return UV_ENOBUFS;
131 case ERROR_BAD_PATHNAME: return UV_ENOENT;
131132 case ERROR_DIRECTORY: return UV_ENOENT;
132133 case ERROR_FILE_NOT_FOUND: return UV_ENOENT;
133134 case ERROR_INVALID_NAME: return UV_ENOENT;
380380
381381 if (handle->dirw) {
382382 /*
383 * We attempt to convert the file name to its long form for
384 * events that still point to valid files on disk.
385 * For removed and renamed events, we do not provide the file name.
383 * We attempt to resolve the long form of the file name explicitly.
384 * We only do this for file names that might still exist on disk.
385 * If this fails, we use the name given by ReadDirectoryChangesW.
386 * This may be the long form or the 8.3 short name in some cases.
386387 */
387388 if (file_info->Action != FILE_ACTION_REMOVED &&
388389 file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {
437438 }
438439
439440 /*
440 * If we couldn't get the long name - just use the name
441 * provided by ReadDirectoryChangesW.
441 * We could not resolve the long form explicitly.
442 * We therefore use the name given by ReadDirectoryChangesW.
443 * This may be the long form or the 8.3 short name in some cases.
442444 */
443445 if (!long_filenamew) {
444446 filenamew = file_info->FileName;
445447 sizew = file_info->FileNameLength / sizeof(WCHAR);
446448 }
447449 } else {
448 /* Removed or renamed callbacks don't provide filename. */
449 filenamew = NULL;
450 /*
451 * Removed or renamed events cannot be resolved to the long form.
452 * We therefore use the name given by ReadDirectoryChangesW.
453 * This may be the long form or the 8.3 short name in some cases.
454 */
455 if (!long_filenamew) {
456 filenamew = file_info->FileName;
457 sizew = file_info->FileNameLength / sizeof(WCHAR);
458 }
450459 }
451460 } else {
452461 /* We already have the long name of the file, so just use it. */
109109 const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
110110 const WCHAR LONG_PATH_PREFIX_LEN = 4;
111111
112 const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
113 const WCHAR UNC_PATH_PREFIX_LEN = 8;
114
112115
113116 void uv_fs_init() {
114117 _fmode = _O_BINARY;
232235 }
233236
234237
238 static int fs__wide_to_utf8(WCHAR* w_source_ptr,
239 DWORD w_source_len,
240 char** target_ptr,
241 uint64_t* target_len_ptr) {
242 int r;
243 int target_len;
244 char* target;
245 target_len = WideCharToMultiByte(CP_UTF8,
246 0,
247 w_source_ptr,
248 w_source_len,
249 NULL,
250 0,
251 NULL,
252 NULL);
253
254 if (target_len == 0) {
255 return -1;
256 }
257
258 if (target_len_ptr != NULL) {
259 *target_len_ptr = target_len;
260 }
261
262 if (target_ptr == NULL) {
263 return 0;
264 }
265
266 target = uv__malloc(target_len + 1);
267 if (target == NULL) {
268 SetLastError(ERROR_OUTOFMEMORY);
269 return -1;
270 }
271
272 r = WideCharToMultiByte(CP_UTF8,
273 0,
274 w_source_ptr,
275 w_source_len,
276 target,
277 target_len,
278 NULL,
279 NULL);
280 assert(r == target_len);
281 target[target_len] = '\0';
282 *target_ptr = target;
283 return 0;
284 }
285
286
235287 INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
236288 uint64_t* target_len_ptr) {
237289 char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
238290 REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
239 WCHAR *w_target;
291 WCHAR* w_target;
240292 DWORD w_target_len;
241 char* target;
242 int target_len;
243293 DWORD bytes;
244294
245295 if (!DeviceIoControl(handle,
332382 return -1;
333383 }
334384
335 /* If needed, compute the length of the target. */
336 if (target_ptr != NULL || target_len_ptr != NULL) {
337 /* Compute the length of the target. */
338 target_len = WideCharToMultiByte(CP_UTF8,
339 0,
340 w_target,
341 w_target_len,
342 NULL,
343 0,
344 NULL,
345 NULL);
346 if (target_len == 0) {
347 return -1;
348 }
349 }
350
351 /* If requested, allocate memory and convert to UTF8. */
352 if (target_ptr != NULL) {
353 int r;
354 target = (char*) uv__malloc(target_len + 1);
355 if (target == NULL) {
356 SetLastError(ERROR_OUTOFMEMORY);
357 return -1;
358 }
359
360 r = WideCharToMultiByte(CP_UTF8,
361 0,
362 w_target,
363 w_target_len,
364 target,
365 target_len,
366 NULL,
367 NULL);
368 assert(r == target_len);
369 target[target_len] = '\0';
370
371 *target_ptr = target;
372 }
373
374 if (target_len_ptr != NULL) {
375 *target_len_ptr = target_len;
376 }
377
378 return 0;
385 return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
379386 }
380387
381388
532539 else
533540 result = 0;
534541
535 SET_REQ_RESULT(req, result);
542 /* _close doesn't set _doserrno on failure, but it does always set errno
543 * to EBADF on failure.
544 */
545 if (result == -1) {
546 assert(errno == EBADF);
547 SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
548 } else {
549 req->result = 0;
550 }
536551 }
537552
538553
16971712 CloseHandle(handle);
16981713 }
16991714
1715
1716 static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
1717 int r;
1718 DWORD w_realpath_len;
1719 WCHAR* w_realpath_ptr;
1720 WCHAR* w_finalpath_ptr = NULL;
1721
1722 w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
1723 if (w_realpath_len == 0) {
1724 return -1;
1725 }
1726
1727 w_realpath_ptr = uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
1728 if (w_realpath_ptr == NULL) {
1729 SetLastError(ERROR_OUTOFMEMORY);
1730 return -1;
1731 }
1732
1733 if (pGetFinalPathNameByHandleW(handle,
1734 w_realpath_ptr,
1735 w_realpath_len,
1736 VOLUME_NAME_DOS) == 0) {
1737 uv__free(w_realpath_ptr);
1738 SetLastError(ERROR_INVALID_HANDLE);
1739 return -1;
1740 }
1741
1742 /* convert UNC path to long path */
1743 if (wcsncmp(w_realpath_ptr,
1744 UNC_PATH_PREFIX,
1745 UNC_PATH_PREFIX_LEN) == 0) {
1746 w_finalpath_ptr = w_realpath_ptr + 6;
1747 *w_finalpath_ptr = L'\\';
1748 } else if (wcsncmp(w_realpath_ptr,
1749 LONG_PATH_PREFIX,
1750 LONG_PATH_PREFIX_LEN) == 0) {
1751 w_finalpath_ptr = w_realpath_ptr + 4;
1752 } else {
1753 uv__free(w_realpath_ptr);
1754 SetLastError(ERROR_INVALID_HANDLE);
1755 return -1;
1756 }
1757
1758 r = fs__wide_to_utf8(w_finalpath_ptr, w_realpath_len, realpath_ptr, NULL);
1759 uv__free(w_realpath_ptr);
1760 return r;
1761 }
1762
1763 static void fs__realpath(uv_fs_t* req) {
1764 HANDLE handle;
1765
1766 if (!pGetFinalPathNameByHandleW) {
1767 SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
1768 return;
1769 }
1770
1771 handle = CreateFileW(req->file.pathw,
1772 0,
1773 0,
1774 NULL,
1775 OPEN_EXISTING,
1776 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
1777 NULL);
1778 if (handle == INVALID_HANDLE_VALUE) {
1779 SET_REQ_WIN32_ERROR(req, GetLastError());
1780 return;
1781 }
1782
1783 if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
1784 CloseHandle(handle);
1785 SET_REQ_WIN32_ERROR(req, GetLastError());
1786 return;
1787 }
1788
1789 CloseHandle(handle);
1790 req->flags |= UV_FS_FREE_PTR;
1791 SET_REQ_RESULT(req, 0);
1792 }
17001793
17011794
17021795 static void fs__chown(uv_fs_t* req) {
17421835 XX(LINK, link)
17431836 XX(SYMLINK, symlink)
17441837 XX(READLINK, readlink)
1838 XX(REALPATH, realpath)
17451839 XX(CHOWN, chown)
17461840 XX(FCHOWN, fchown);
17471841 default:
20662160 }
20672161
20682162
2163 int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
2164 uv_fs_cb cb) {
2165 int err;
2166
2167 if (!req || !path) {
2168 return UV_EINVAL;
2169 }
2170
2171 uv_fs_req_init(loop, req, UV_FS_REALPATH, cb);
2172
2173 err = fs__capture_path(req, path, NULL, cb != NULL);
2174 if (err) {
2175 return uv_translate_sys_error(err);
2176 }
2177
2178 if (cb) {
2179 QUEUE_FS_TP_JOB(loop, req);
2180 return 0;
2181 } else {
2182 fs__realpath(req);
2183 return req->result;
2184 }
2185 }
2186
2187
20692188 int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
20702189 uv_gid_t gid, uv_fs_cb cb) {
20712190 int err;
108108 req = container_of(w, uv_getaddrinfo_t, work_req);
109109
110110 /* release input parameter memory */
111 if (req->alloc != NULL) {
112 uv__free(req->alloc);
113 req->alloc = NULL;
114 }
111 uv__free(req->alloc);
112 req->alloc = NULL;
115113
116114 if (status == UV_ECANCELED) {
117115 assert(req->retcode == 0);
218216 char* alloc_ptr = (char*)ai;
219217
220218 /* release copied result memory */
221 if (alloc_ptr != NULL) {
222 uv__free(alloc_ptr);
223 }
219 uv__free(alloc_ptr);
224220 }
225221
226222
353349 }
354350
355351 error:
356 if (req != NULL && req->alloc != NULL) {
352 if (req != NULL) {
357353 uv__free(req->alloc);
354 req->alloc = NULL;
358355 }
359356 return uv_translate_sys_error(err);
360357 }
326326
327327 uint64_t uv__hrtime(double scale);
328328 int uv_parent_pid();
329 int uv_current_pid();
329330 __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
330331
331332
8484
8585
8686 static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {
87 _snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId());
87 snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId());
8888 }
8989
9090
12451245 if (send_handle) {
12461246 tcp_send_handle = (uv_tcp_t*)send_handle;
12471247
1248 if (handle->pipe.conn.ipc_pid == 0) {
1249 handle->pipe.conn.ipc_pid = uv_current_pid();
1250 }
1251
12481252 err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid,
12491253 &ipc_frame.socket_info_ex.socket_info);
12501254 if (err) {
16281632
16291633 if (ReadFile(handle->handle,
16301634 buf.base,
1631 buf.len,
1635 min(buf.len, avail),
16321636 &bytes,
16331637 NULL)) {
16341638 /* Successful read */
0 /* Copyright the libuv project contributors. All rights reserved.
1 *
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
3 * of this software and associated documentation files (the "Software"), to
4 * deal in the Software without restriction, including without limitation the
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6 * sell copies of the Software, and to permit persons to whom the Software is
7 * furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18 * IN THE SOFTWARE.
19 */
20
21 #if defined(_MSC_VER) && _MSC_VER < 1900
22
23 #include <stdio.h>
24 #include <stdarg.h>
25
26 /* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer
27 * on overflow...
28 */
29 int snprintf(char* buf, size_t len, const char* fmt, ...) {
30 int n;
31 va_list ap;
32 va_start(ap, fmt);
33
34 n = _vscprintf(fmt, ap);
35 vsnprintf_s(buf, len, _TRUNCATE, fmt, ap);
36
37 va_end(ap);
38 return n;
39 }
40
41 #endif
207207 static int style_captured = 0;
208208
209209 /* Only do this once.
210 /* Assumption: Caller has acquired uv_tty_output_lock. */
210 Assumption: Caller has acquired uv_tty_output_lock. */
211211 if (style_captured)
212212 return;
213213
5858 static char *process_title;
5959 static CRITICAL_SECTION process_title_lock;
6060
61 /* Cached copy of the process id, written once. */
62 static DWORD current_pid = 0;
63
64
6165 /* Interval (in seconds) of the high-resolution clock. */
6266 static double hrtime_interval_ = 0;
6367
355359
356360 CloseHandle(handle);
357361 return parent_pid;
362 }
363
364
365 int uv_current_pid() {
366 if (current_pid == 0) {
367 current_pid = GetCurrentProcessId();
368 }
369 return current_pid;
358370 }
359371
360372
4545 sWakeAllConditionVariable pWakeAllConditionVariable;
4646 sWakeConditionVariable pWakeConditionVariable;
4747 sCancelSynchronousIo pCancelSynchronousIo;
48 sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
4849
4950
5051 void uv_winapi_init() {
138139
139140 pCancelSynchronousIo = (sCancelSynchronousIo)
140141 GetProcAddress(kernel32_module, "CancelSynchronousIo");
142
143 pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW)
144 GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW");
141145 }
46774677 typedef BOOL (WINAPI* sCancelSynchronousIo)
46784678 (HANDLE hThread);
46794679
4680 typedef DWORD (WINAPI* sGetFinalPathNameByHandleW)
4681 (HANDLE hFile,
4682 LPWSTR lpszFilePath,
4683 DWORD cchFilePath,
4684 DWORD dwFlags);
4685
46804686 /* Ntdll function pointers */
46814687 extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
46824688 extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
46984704 extern sWakeAllConditionVariable pWakeAllConditionVariable;
46994705 extern sWakeConditionVariable pWakeConditionVariable;
47004706 extern sCancelSynchronousIo pCancelSynchronousIo;
4707 extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
47014708
47024709 #endif /* UV_WIN_WINAPI_H_ */
1818 * IN THE SOFTWARE.
1919 */
2020
21 /* Don't complain about _snprintf being insecure. */
22 #define _CRT_SECURE_NO_WARNINGS
23
2421 /* Don't complain about write(), fileno() etc. being deprecated. */
2522 #pragma warning(disable : 4996)
2623
2926 #include <windows.h>
3027 #include <stdio.h>
3128
32
33 /* Windows has no snprintf, only _snprintf. */
34 #define snprintf _snprintf
35
29 #if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
30 extern int snprintf(char*, size_t, const char*, ...);
31 #endif
3632
3733 typedef struct {
3834 HANDLE process;
209209 #ifndef _WIN32
210210 /* Clean up stale socket from previous run. */
211211 remove(TEST_PIPENAME);
212 remove(TEST_PIPENAME_2);
213 remove(TEST_PIPENAME_3);
212214 #endif
213215
214216 /* If it's a helper the user asks for, start it directly. */
4949 #ifdef _WIN32
5050 # define TEST_PIPENAME "\\\\?\\pipe\\uv-test"
5151 # define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2"
52 # define TEST_PIPENAME_3 "\\\\?\\pipe\\uv-test3"
5253 #else
5354 # define TEST_PIPENAME "/tmp/uv-test-sock"
5455 # define TEST_PIPENAME_2 "/tmp/uv-test-sock2"
56 # define TEST_PIPENAME_3 "/tmp/uv-test-sock3"
5557 #endif
5658
5759 #ifdef _WIN32
173175
174176 #endif
175177
176
177 #if defined _WIN32 && ! defined __GNUC__
178
179 #include <stdarg.h>
180
181 /* Define inline for MSVC<2015 */
182 # if defined(_MSC_VER) && _MSC_VER < 1900
183 # define inline __inline
184 # endif
185
186 # if defined(_MSC_VER) && _MSC_VER < 1900
187 /* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer
188 * on overflow...
189 */
190 inline int snprintf(char* buf, size_t len, const char* fmt, ...) {
191 va_list ap;
192 int n;
193
194 va_start(ap, fmt);
195 n = _vsprintf_p(buf, len, fmt, ap);
196 va_end(ap);
197
198 /* It's a sad fact of life that no one ever checks the return value of
199 * snprintf(). Zero-terminating the buffer hopefully reduces the risk
200 * of gaping security holes.
201 */
202 if (n < 0)
203 if (len > 0)
204 buf[0] = '\0';
205
206 return n;
207 }
208 # endif
209
178 #if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
179 extern int snprintf(char*, size_t, const char*, ...);
210180 #endif
211181
212182 #if defined(__clang__) || \
2424 #include "task.h"
2525
2626 #include <errno.h>
27 #include <stdio.h>
2827 #include <sys/resource.h>
2928 #include <unistd.h>
3029
4443 uv_loop_t* loop;
4544 int first_fd;
4645
46 /* Lower the file descriptor limit and use up all fds save one. */
47 limits.rlim_cur = limits.rlim_max = maxfd + 1;
48 if (setrlimit(RLIMIT_NOFILE, &limits)) {
49 ASSERT(errno == EPERM); /* Valgrind blocks the setrlimit() call. */
50 RETURN_SKIP("setrlimit(RLIMIT_NOFILE) failed, running under valgrind?");
51 }
52
4753 loop = uv_default_loop();
4854 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
4955 ASSERT(0 == uv_tcp_init(loop, &server_handle));
5056 ASSERT(0 == uv_tcp_init(loop, &client_handle));
5157 ASSERT(0 == uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0));
5258 ASSERT(0 == uv_listen((uv_stream_t*) &server_handle, 8, connection_cb));
53
54 /* Lower the file descriptor limit and use up all fds save one. */
55 limits.rlim_cur = limits.rlim_max = maxfd + 1;
56 if (setrlimit(RLIMIT_NOFILE, &limits)) {
57 perror("setrlimit(RLIMIT_NOFILE)");
58 ASSERT(0);
59 }
6059
6160 /* Remember the first one so we can clean up afterwards. */
6261 do
114114 ASSERT(handle == &fs_event);
115115 ASSERT(status == 0);
116116 ASSERT(events == UV_RENAME);
117 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
118 ASSERT(strcmp(filename, "file1") == 0);
119 #else
117120 ASSERT(filename == NULL || strcmp(filename, "file1") == 0);
121 #endif
118122 ASSERT(0 == uv_fs_event_stop(handle));
119123 uv_close((uv_handle_t*)handle, close_cb);
120124 }
177181 ASSERT(handle == &fs_event);
178182 ASSERT(status == 0);
179183 ASSERT(events == UV_CHANGE || UV_RENAME);
184 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
185 ASSERT(strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
186 #else
180187 ASSERT(filename == NULL ||
181188 strncmp(filename, file_prefix, sizeof(file_prefix) - 1) == 0);
189 #endif
182190
183191 if (fs_event_created + fs_event_removed == fs_event_file_count) {
184192 /* Once we've processed all create events, delete all files */
249257 ASSERT(handle == &fs_event);
250258 ASSERT(status == 0);
251259 ASSERT(events == UV_CHANGE || UV_RENAME);
260 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
261 ASSERT(strncmp(filename,
262 file_prefix_in_subdir,
263 sizeof(file_prefix_in_subdir) - 1) == 0);
264 #else
252265 ASSERT(filename == NULL ||
253 strncmp(filename, file_prefix_in_subdir, sizeof(file_prefix_in_subdir) - 1) == 0);
266 strncmp(filename,
267 file_prefix_in_subdir,
268 sizeof(file_prefix_in_subdir) - 1) == 0);
269 #endif
254270
255271 if (fs_event_created + fs_event_removed == fs_event_file_count) {
256272 /* Once we've processed all create events, delete all files */
269285 ASSERT(handle == &fs_event);
270286 ASSERT(status == 0);
271287 ASSERT(events == UV_CHANGE);
288 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
289 ASSERT(strcmp(filename, "file2") == 0);
290 #else
272291 ASSERT(filename == NULL || strcmp(filename, "file2") == 0);
292 #endif
273293 ASSERT(0 == uv_fs_event_stop(handle));
274294 uv_close((uv_handle_t*)handle, close_cb);
275295 }
292312 ASSERT(handle == &fs_event);
293313 ASSERT(status == 0);
294314 ASSERT(events == UV_CHANGE);
315 #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
316 ASSERT(strcmp(filename, "watch_file") == 0);
317 #else
295318 ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
319 #endif
296320
297321 /* Regression test for SunOS: touch should generate just one event. */
298322 {
486510 r = uv_timer_init(loop, &timer);
487511 ASSERT(r == 0);
488512
489 r = uv_timer_start(&timer, timer_cb_touch, 1, 0);
513 r = uv_timer_start(&timer, timer_cb_touch, 10, 0);
490514 ASSERT(r == 0);
491515
492516 ASSERT(timer_cb_touch_called == 0);
8282 static int link_cb_count;
8383 static int symlink_cb_count;
8484 static int readlink_cb_count;
85 static int realpath_cb_count;
8586 static int utime_cb_count;
8687 static int futime_cb_count;
8788
163164 ASSERT(req->result == 0);
164165 ASSERT(strcmp(req->ptr, "test_file_symlink2") == 0);
165166 readlink_cb_count++;
167 uv_fs_req_cleanup(req);
168 }
169
170
171 static void realpath_cb(uv_fs_t* req) {
172 char test_file_abs_buf[PATHMAX];
173 size_t test_file_abs_size = sizeof(test_file_abs_buf);
174 ASSERT(req->fs_type == UV_FS_REALPATH);
175 #ifdef _WIN32
176 /*
177 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
178 */
179 if (req->result == UV_ENOSYS) {
180 realpath_cb_count++;
181 uv_fs_req_cleanup(req);
182 return;
183 }
184 #endif
185 ASSERT(req->result == 0);
186
187 uv_cwd(test_file_abs_buf, &test_file_abs_size);
188 #ifdef _WIN32
189 strcat(test_file_abs_buf, "\\test_file");
190 ASSERT(stricmp(req->ptr, test_file_abs_buf) == 0);
191 #else
192 strcat(test_file_abs_buf, "/test_file");
193 ASSERT(strcmp(req->ptr, test_file_abs_buf) == 0);
194 #endif
195 realpath_cb_count++;
166196 uv_fs_req_cleanup(req);
167197 }
168198
15641594 }
15651595
15661596
1597 TEST_IMPL(fs_realpath) {
1598 uv_fs_t req;
1599
1600 loop = uv_default_loop();
1601 ASSERT(0 == uv_fs_realpath(loop, &req, "no_such_file", dummy_cb));
1602 ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
1603 ASSERT(dummy_cb_count == 1);
1604 ASSERT(req.ptr == NULL);
1605 #ifdef _WIN32
1606 /*
1607 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1608 */
1609 if (req.result == UV_ENOSYS) {
1610 uv_fs_req_cleanup(&req);
1611 RETURN_SKIP("realpath is not supported on Windows XP");
1612 }
1613 #endif
1614 ASSERT(req.result == UV_ENOENT);
1615 uv_fs_req_cleanup(&req);
1616
1617 ASSERT(UV_ENOENT == uv_fs_realpath(NULL, &req, "no_such_file", NULL));
1618 ASSERT(req.ptr == NULL);
1619 ASSERT(req.result == UV_ENOENT);
1620 uv_fs_req_cleanup(&req);
1621
1622 MAKE_VALGRIND_HAPPY();
1623 return 0;
1624 }
1625
1626
15671627 TEST_IMPL(fs_symlink) {
15681628 int r;
15691629 uv_fs_t req;
15701630 uv_file file;
15711631 uv_file link;
1632 char test_file_abs_buf[PATHMAX];
1633 size_t test_file_abs_size;
15721634
15731635 /* Setup. */
15741636 unlink("test_file");
15761638 unlink("test_file_symlink2");
15771639 unlink("test_file_symlink_symlink");
15781640 unlink("test_file_symlink2_symlink");
1641 test_file_abs_size = sizeof(test_file_abs_buf);
1642 #ifdef _WIN32
1643 uv_cwd(test_file_abs_buf, &test_file_abs_size);
1644 strcat(test_file_abs_buf, "\\test_file");
1645 #else
1646 uv_cwd(test_file_abs_buf, &test_file_abs_size);
1647 strcat(test_file_abs_buf, "/test_file");
1648 #endif
15791649
15801650 loop = uv_default_loop();
15811651
16461716 ASSERT(strcmp(req.ptr, "test_file_symlink") == 0);
16471717 uv_fs_req_cleanup(&req);
16481718
1719 r = uv_fs_realpath(NULL, &req, "test_file_symlink_symlink", NULL);
1720 #ifdef _WIN32
1721 /*
1722 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1723 */
1724 if (r == UV_ENOSYS) {
1725 uv_fs_req_cleanup(&req);
1726 RETURN_SKIP("realpath is not supported on Windows XP");
1727 }
1728 #endif
1729 ASSERT(r == 0);
1730 #ifdef _WIN32
1731 ASSERT(stricmp(req.ptr, test_file_abs_buf) == 0);
1732 #else
1733 ASSERT(strcmp(req.ptr, test_file_abs_buf) == 0);
1734 #endif
1735 uv_fs_req_cleanup(&req);
1736
16491737 /* async link */
16501738 r = uv_fs_symlink(loop,
16511739 &req,
16861774 uv_run(loop, UV_RUN_DEFAULT);
16871775 ASSERT(readlink_cb_count == 1);
16881776
1777 r = uv_fs_realpath(loop, &req, "test_file", realpath_cb);
1778 #ifdef _WIN32
1779 /*
1780 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1781 */
1782 if (r == UV_ENOSYS) {
1783 uv_fs_req_cleanup(&req);
1784 RETURN_SKIP("realpath is not supported on Windows XP");
1785 }
1786 #endif
1787 ASSERT(r == 0);
1788 uv_run(loop, UV_RUN_DEFAULT);
1789 ASSERT(realpath_cb_count == 1);
1790
16891791 /*
16901792 * Run the loop just to check we don't have make any extraneous uv_ref()
16911793 * calls. This should drop out immediately.
17091811 int r;
17101812 char* test_dir;
17111813 uv_dirent_t dent;
1814 static char test_dir_abs_buf[PATHMAX];
1815 size_t test_dir_abs_size;
17121816
17131817 /* set-up */
17141818 unlink("test_dir/file1");
17151819 unlink("test_dir/file2");
17161820 rmdir("test_dir");
17171821 rmdir("test_dir_symlink");
1822 test_dir_abs_size = sizeof(test_dir_abs_buf);
17181823
17191824 loop = uv_default_loop();
17201825
17221827 uv_fs_req_cleanup(&req);
17231828
17241829 #ifdef _WIN32
1725 {
1726 static char src_path_buf[PATHMAX];
1727 size_t size;
1728 size = sizeof(src_path_buf);
1729 strcpy(src_path_buf, "\\\\?\\");
1730 uv_cwd(src_path_buf + 4, &size);
1731 strcat(src_path_buf, "\\test_dir\\");
1732 test_dir = src_path_buf;
1733 }
1830 strcpy(test_dir_abs_buf, "\\\\?\\");
1831 uv_cwd(test_dir_abs_buf + 4, &test_dir_abs_size);
1832 test_dir_abs_size += 4;
1833 strcat(test_dir_abs_buf, "\\test_dir\\");
1834 test_dir_abs_size += strlen("\\test_dir\\");
1835 test_dir = test_dir_abs_buf;
17341836 #else
1837 uv_cwd(test_dir_abs_buf, &test_dir_abs_size);
1838 strcat(test_dir_abs_buf, "/test_dir");
1839 test_dir_abs_size += strlen("/test_dir");
17351840 test_dir = "test_dir";
17361841 #endif
17371842
17631868 ASSERT(strcmp(req.ptr, test_dir + 4) == 0);
17641869 #else
17651870 ASSERT(strcmp(req.ptr, test_dir) == 0);
1871 #endif
1872 uv_fs_req_cleanup(&req);
1873
1874 r = uv_fs_realpath(NULL, &req, "test_dir_symlink", NULL);
1875 #ifdef _WIN32
1876 /*
1877 * Windows XP and Server 2003 don't support GetFinalPathNameByHandleW()
1878 */
1879 if (r == UV_ENOSYS) {
1880 uv_fs_req_cleanup(&req);
1881 RETURN_SKIP("realpath is not supported on Windows XP");
1882 }
1883 #endif
1884 ASSERT(r == 0);
1885 #ifdef _WIN32
1886 ASSERT(strlen(req.ptr) == test_dir_abs_size - 5);
1887 ASSERT(strnicmp(req.ptr, test_dir + 4, test_dir_abs_size - 5) == 0);
1888 #else
1889 ASSERT(strcmp(req.ptr, test_dir_abs_buf) == 0);
17661890 #endif
17671891 uv_fs_req_cleanup(&req);
17681892
2323
2424 TEST_IMPL(get_loadavg) {
2525
26 double avg[3];
26 double avg[3] = {-1, -1, -1};
2727 uv_loadavg(avg);
2828
29 ASSERT(avg != NULL);
3029 ASSERT(avg[0] >= 0);
3130 ASSERT(avg[1] >= 0);
3231 ASSERT(avg[2] >= 0);
8282 TEST_IMPL(getaddrinfo_fail) {
8383 uv_getaddrinfo_t req;
8484
85 /* Use a FQDN by ending in a period */
8586 ASSERT(0 == uv_getaddrinfo(uv_default_loop(),
8687 &req,
8788 getaddrinfo_fail_cb,
88 "xyzzy.xyzzy.xyzzy",
89 "xyzzy.xyzzy.xyzzy.",
8990 NULL,
9091 NULL));
9192 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
99100 TEST_IMPL(getaddrinfo_fail_sync) {
100101 uv_getaddrinfo_t req;
101102
103 /* Use a FQDN by ending in a period */
102104 ASSERT(0 > uv_getaddrinfo(uv_default_loop(),
103105 &req,
104106 NULL,
105 "xyzzy.xyzzy.xyzzy",
107 "xyzzy.xyzzy.xyzzy.",
106108 NULL,
107109 NULL));
108110 uv_freeaddrinfo(req.addrinfo);
7272 NULL,
7373 (const struct sockaddr*)&addr4,
7474 0));
75 ASSERT(req.host != NULL);
76 ASSERT(req.service != NULL);
75 ASSERT(req.host[0] != '\0');
76 ASSERT(req.service[0] != '\0');
7777
7878 MAKE_VALGRIND_HAPPY();
7979 return 0;
2929 uv_process_t* process,
3030 const char* helper);
3131
32 void ipc_send_recv_helper_threadproc(void* arg);
33
3234 union handles {
3335 uv_handle_t handle;
3436 uv_stream_t stream;
3739 uv_tty_t tty;
3840 };
3941
42 struct test_ctx {
43 uv_pipe_t channel;
44 uv_connect_t connect_req;
45 uv_write_t write_req;
46 uv_write_t write_req2;
47 uv_handle_type expected_type;
48 union handles send;
49 union handles send2;
50 union handles recv;
51 union handles recv2;
52 };
53
4054 struct echo_ctx {
55 uv_pipe_t listen;
4156 uv_pipe_t channel;
4257 uv_write_t write_req;
58 uv_write_t write_req2;
4359 uv_handle_type expected_type;
44 union handles send;
4560 union handles recv;
61 union handles recv2;
4662 };
4763
48 static struct echo_ctx ctx;
49 static int num_recv_handles;
64 static struct test_ctx ctx;
65 static struct echo_ctx ctx2;
66
67 /* Used in write2_cb to decide if we need to cleanup or not */
68 static int is_child_process;
69 static int is_in_process;
70 static int read_cb_called;
71 static int recv_cb_called;
72 static int write2_cb_called;
5073
5174
5275 static void alloc_cb(uv_handle_t* handle,
6588 uv_handle_type pending;
6689 uv_pipe_t* pipe;
6790 int r;
91 union handles* recv;
92
93 if (++recv_cb_called == 1) {
94 recv = &ctx.recv;
95 } else {
96 recv = &ctx.recv2;
97 }
6898
6999 pipe = (uv_pipe_t*) handle;
70100 ASSERT(pipe == &ctx.channel);
71 ASSERT(nread >= 0);
72 ASSERT(1 == uv_pipe_pending_count(pipe));
73
74 pending = uv_pipe_pending_type(pipe);
75 ASSERT(pending == ctx.expected_type);
76
77 if (pending == UV_NAMED_PIPE)
78 r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0);
79 else if (pending == UV_TCP)
80 r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp);
81 else
82 abort();
83 ASSERT(r == 0);
84
85 r = uv_accept(handle, &ctx.recv.stream);
86 ASSERT(r == 0);
87
88 uv_close((uv_handle_t*)&ctx.channel, NULL);
89 uv_close(&ctx.send.handle, NULL);
90 uv_close(&ctx.recv.handle, NULL);
91 num_recv_handles++;
92 }
93
94
95 static int run_test(void) {
96 uv_process_t process;
101
102 /* Depending on the OS, the final recv_cb can be called after the child
103 * process has terminated which can result in nread being UV_EOF instead of
104 * the number of bytes read. Since the other end of the pipe has closed this
105 * UV_EOF is an acceptable value. */
106 if (nread == UV_EOF) {
107 /* UV_EOF is only acceptable for the final recv_cb call */
108 ASSERT(recv_cb_called == 2);
109 } else {
110 ASSERT(nread >= 0);
111 ASSERT(1 == uv_pipe_pending_count(pipe));
112
113 pending = uv_pipe_pending_type(pipe);
114 ASSERT(pending == ctx.expected_type);
115
116 if (pending == UV_NAMED_PIPE)
117 r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0);
118 else if (pending == UV_TCP)
119 r = uv_tcp_init(ctx.channel.loop, &recv->tcp);
120 else
121 abort();
122 ASSERT(r == 0);
123
124 r = uv_accept(handle, &recv->stream);
125 ASSERT(r == 0);
126 }
127
128 /* Close after two writes received */
129 if (recv_cb_called == 2) {
130 uv_close((uv_handle_t*)&ctx.channel, NULL);
131 }
132 }
133
134 static void connect_cb(uv_connect_t* req, int status) {
135 int r;
97136 uv_buf_t buf;
98 int r;
99
100 spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper");
137
138 ASSERT(req == &ctx.connect_req);
139 ASSERT(status == 0);
101140
102141 buf = uv_buf_init(".", 1);
103142 r = uv_write2(&ctx.write_req,
107146 NULL);
108147 ASSERT(r == 0);
109148
149 /* Perform two writes to the same pipe to make sure that on Windows we are
150 * not running into issue 505:
151 * https://github.com/libuv/libuv/issues/505 */
152 buf = uv_buf_init(".", 1);
153 r = uv_write2(&ctx.write_req2,
154 (uv_stream_t*)&ctx.channel,
155 &buf, 1,
156 &ctx.send2.stream,
157 NULL);
158 ASSERT(r == 0);
159
110160 r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb);
111161 ASSERT(r == 0);
162 }
163
164 static int run_test(int inprocess) {
165 uv_process_t process;
166 uv_thread_t tid;
167 int r;
168
169 if (inprocess) {
170 r = uv_thread_create(&tid, ipc_send_recv_helper_threadproc, (void *) 42);
171 ASSERT(r == 0);
172
173 uv_sleep(1000);
174
175 r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1);
176 ASSERT(r == 0);
177
178 uv_pipe_connect(&ctx.connect_req, &ctx.channel, TEST_PIPENAME_3, connect_cb);
179 } else {
180 spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper");
181
182 connect_cb(&ctx.connect_req, 0);
183 }
112184
113185 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
114186 ASSERT(r == 0);
115187
116 ASSERT(num_recv_handles == 1);
188 ASSERT(recv_cb_called == 2);
189
190 if (inprocess) {
191 r = uv_thread_join(&tid);
192 ASSERT(r == 0);
193 }
117194
118195 return 0;
119196 }
120197
121
122 TEST_IMPL(ipc_send_recv_pipe) {
198 static int run_ipc_send_recv_pipe(int inprocess) {
123199 int r;
124200
125201 ctx.expected_type = UV_NAMED_PIPE;
130206 r = uv_pipe_bind(&ctx.send.pipe, TEST_PIPENAME);
131207 ASSERT(r == 0);
132208
133 r = run_test();
209 r = uv_pipe_init(uv_default_loop(), &ctx.send2.pipe, 1);
210 ASSERT(r == 0);
211
212 r = uv_pipe_bind(&ctx.send2.pipe, TEST_PIPENAME_2);
213 ASSERT(r == 0);
214
215 r = run_test(inprocess);
134216 ASSERT(r == 0);
135217
136218 MAKE_VALGRIND_HAPPY();
137219 return 0;
138220 }
139221
140
141 TEST_IMPL(ipc_send_recv_tcp) {
222 TEST_IMPL(ipc_send_recv_pipe) {
223 return run_ipc_send_recv_pipe(0);
224 }
225
226 TEST_IMPL(ipc_send_recv_pipe_inprocess) {
227 return run_ipc_send_recv_pipe(1);
228 }
229
230 static int run_ipc_send_recv_tcp(int inprocess) {
142231 struct sockaddr_in addr;
143232 int r;
144233
149238 r = uv_tcp_init(uv_default_loop(), &ctx.send.tcp);
150239 ASSERT(r == 0);
151240
241 r = uv_tcp_init(uv_default_loop(), &ctx.send2.tcp);
242 ASSERT(r == 0);
243
152244 r = uv_tcp_bind(&ctx.send.tcp, (const struct sockaddr*) &addr, 0);
153245 ASSERT(r == 0);
154246
155 r = run_test();
247 r = uv_tcp_bind(&ctx.send2.tcp, (const struct sockaddr*) &addr, 0);
248 ASSERT(r == 0);
249
250 r = run_test(inprocess);
156251 ASSERT(r == 0);
157252
158253 MAKE_VALGRIND_HAPPY();
159254 return 0;
160255 }
161256
162
163 /* Everything here runs in a child process. */
257 TEST_IMPL(ipc_send_recv_tcp) {
258 return run_ipc_send_recv_tcp(0);
259 }
260
261 TEST_IMPL(ipc_send_recv_tcp_inprocess) {
262 return run_ipc_send_recv_tcp(1);
263 }
264
265
266 /* Everything here runs in a child process or second thread. */
164267
165268 static void write2_cb(uv_write_t* req, int status) {
166269 ASSERT(status == 0);
167 uv_close(&ctx.recv.handle, NULL);
168 uv_close((uv_handle_t*)&ctx.channel, NULL);
169 }
170
270
271 /* After two successful writes in the child process, allow the child
272 * process to be closed. */
273 if (++write2_cb_called == 2 && (is_child_process || is_in_process)) {
274 uv_close(&ctx2.recv.handle, NULL);
275 uv_close(&ctx2.recv2.handle, NULL);
276 uv_close((uv_handle_t*)&ctx2.channel, NULL);
277 uv_close((uv_handle_t*)&ctx2.listen, NULL);
278 }
279 }
171280
172281 static void read_cb(uv_stream_t* handle,
173282 ssize_t nread,
176285 uv_pipe_t* pipe;
177286 uv_handle_type pending;
178287 int r;
288 union handles* recv;
289 uv_write_t* write_req;
290
291 if (nread == UV__EOF || nread == UV__ECONNABORTED) {
292 return;
293 }
294
295 if (++read_cb_called == 2) {
296 recv = &ctx2.recv;
297 write_req = &ctx2.write_req;
298 } else {
299 recv = &ctx2.recv2;
300 write_req = &ctx2.write_req2;
301 }
179302
180303 pipe = (uv_pipe_t*) handle;
181 ASSERT(pipe == &ctx.channel);
304 ASSERT(pipe == &ctx2.channel);
182305 ASSERT(nread >= 0);
183306 ASSERT(1 == uv_pipe_pending_count(pipe));
184307
185308 pending = uv_pipe_pending_type(pipe);
186309 ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP);
187310
188 wrbuf = uv_buf_init(".", 1);
189
190311 if (pending == UV_NAMED_PIPE)
191 r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0);
312 r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0);
192313 else if (pending == UV_TCP)
193 r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp);
314 r = uv_tcp_init(ctx2.channel.loop, &recv->tcp);
194315 else
195316 abort();
196317 ASSERT(r == 0);
197318
198 r = uv_accept(handle, &ctx.recv.stream);
199 ASSERT(r == 0);
200
201 r = uv_write2(&ctx.write_req,
202 (uv_stream_t*)&ctx.channel,
319 r = uv_accept(handle, &recv->stream);
320 ASSERT(r == 0);
321
322 wrbuf = uv_buf_init(".", 1);
323 r = uv_write2(write_req,
324 (uv_stream_t*)&ctx2.channel,
203325 &wrbuf,
204326 1,
205 &ctx.recv.stream,
327 &recv->stream,
206328 write2_cb);
207329 ASSERT(r == 0);
208330 }
209331
332 static void send_recv_start() {
333 int r;
334 ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx2.channel));
335 ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx2.channel));
336 ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx2.channel));
337
338 r = uv_read_start((uv_stream_t*)&ctx2.channel, alloc_cb, read_cb);
339 ASSERT(r == 0);
340 }
341
342 static void listen_cb(uv_stream_t* handle, int status) {
343 int r;
344 ASSERT(handle == (uv_stream_t*)&ctx2.listen);
345 ASSERT(status == 0);
346
347 r = uv_accept((uv_stream_t*)&ctx2.listen, (uv_stream_t*)&ctx2.channel);
348 ASSERT(r == 0);
349
350 send_recv_start();
351 }
352
353 int run_ipc_send_recv_helper(uv_loop_t* loop, int inprocess) {
354 int r;
355
356 is_in_process = inprocess;
357
358 memset(&ctx2, 0, sizeof(ctx2));
359
360 r = uv_pipe_init(loop, &ctx2.listen, 0);
361 ASSERT(r == 0);
362
363 r = uv_pipe_init(loop, &ctx2.channel, 1);
364 ASSERT(r == 0);
365
366 if (inprocess) {
367 r = uv_pipe_bind(&ctx2.listen, TEST_PIPENAME_3);
368 ASSERT(r == 0);
369
370 r = uv_listen((uv_stream_t*)&ctx2.listen, SOMAXCONN, listen_cb);
371 ASSERT(r == 0);
372 } else {
373 r = uv_pipe_open(&ctx2.channel, 0);
374 ASSERT(r == 0);
375
376 send_recv_start();
377 }
378
379 r = uv_run(loop, UV_RUN_DEFAULT);
380 ASSERT(r == 0);
381
382 return 0;
383 }
210384
211385 /* stdin is a duplex channel over which a handle is sent.
212386 * We receive it and send it back where it came from.
214388 int ipc_send_recv_helper(void) {
215389 int r;
216390
217 memset(&ctx, 0, sizeof(ctx));
218
219 r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1);
220 ASSERT(r == 0);
221
222 uv_pipe_open(&ctx.channel, 0);
223 ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel));
224 ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel));
225 ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel));
226
227 r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, read_cb);
228 ASSERT(r == 0);
229
230 r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
391 r = run_ipc_send_recv_helper(uv_default_loop(), 0);
231392 ASSERT(r == 0);
232393
233394 MAKE_VALGRIND_HAPPY();
234395 return 0;
235396 }
397
398 void ipc_send_recv_helper_threadproc(void* arg) {
399 int r;
400 uv_loop_t loop;
401
402 r = uv_loop_init(&loop);
403 ASSERT(r == 0);
404
405 r = run_ipc_send_recv_helper(&loop, 1);
406 ASSERT(r == 0);
407
408 r = uv_loop_close(&loop);
409 ASSERT(r == 0);
410 }
4949 TEST_DECLARE (ipc_listen_after_write)
5050 #ifndef _WIN32
5151 TEST_DECLARE (ipc_send_recv_pipe)
52 TEST_DECLARE (ipc_send_recv_pipe_inprocess)
5253 #endif
5354 TEST_DECLARE (ipc_send_recv_tcp)
55 TEST_DECLARE (ipc_send_recv_tcp_inprocess)
5456 TEST_DECLARE (ipc_tcp_connection)
5557 TEST_DECLARE (tcp_ping_pong)
5658 TEST_DECLARE (tcp_ping_pong_v6)
251253 TEST_DECLARE (fs_chown)
252254 TEST_DECLARE (fs_link)
253255 TEST_DECLARE (fs_readlink)
256 TEST_DECLARE (fs_realpath)
254257 TEST_DECLARE (fs_symlink)
255258 TEST_DECLARE (fs_symlink_dir)
256259 TEST_DECLARE (fs_utime)
333336 HELPER_DECLARE (udp4_echo_server)
334337 HELPER_DECLARE (pipe_echo_server)
335338
339 TEST_DECLARE (queue_foreach_delete)
336340
337341 TASK_LIST_START
338342 TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000)
379383 TEST_ENTRY (ipc_listen_after_write)
380384 #ifndef _WIN32
381385 TEST_ENTRY (ipc_send_recv_pipe)
386 TEST_ENTRY (ipc_send_recv_pipe_inprocess)
382387 #endif
383388 TEST_ENTRY (ipc_send_recv_tcp)
389 TEST_ENTRY (ipc_send_recv_tcp_inprocess)
384390 TEST_ENTRY (ipc_tcp_connection)
385391
386392 TEST_ENTRY (tcp_ping_pong)
670676 TEST_ENTRY (fs_utime)
671677 TEST_ENTRY (fs_futime)
672678 TEST_ENTRY (fs_readlink)
679 TEST_ENTRY (fs_realpath)
673680 TEST_ENTRY (fs_symlink)
674681 TEST_ENTRY (fs_symlink_dir)
675682 TEST_ENTRY (fs_stat_missing_path)
713720 TEST_ENTRY (dlerror)
714721 TEST_ENTRY (ip4_addr)
715722 TEST_ENTRY (ip6_addr_link_local)
723
724 TEST_ENTRY (queue_foreach_delete)
725
716726 #if 0
717727 /* These are for testing the test runner. */
718728 TEST_ENTRY (fail_always)
2424 #include <stdio.h>
2525 #include <stdlib.h>
2626
27 static uv_cond_t condvar;
28 static uv_mutex_t mutex;
29 static uv_rwlock_t rwlock;
30 static int step;
2731
2832 /* The mutex and rwlock tests are really poor.
2933 * They're very basic sanity checks and nothing more.
6266 }
6367
6468
65 TEST_IMPL(thread_rwlock_trylock) {
66 uv_rwlock_t rwlock;
67 int r;
69 /* Call when holding |mutex|. */
70 static void synchronize_nowait(void) {
71 step += 1;
72 uv_cond_signal(&condvar);
73 }
6874
69 r = uv_rwlock_init(&rwlock);
70 ASSERT(r == 0);
7175
72 /* No locks held. */
76 /* Call when holding |mutex|. */
77 static void synchronize(void) {
78 int current;
7379
74 r = uv_rwlock_trywrlock(&rwlock);
75 ASSERT(r == 0);
80 synchronize_nowait();
81 /* Wait for the other thread. Guard against spurious wakeups. */
82 for (current = step; current == step; uv_cond_wait(&condvar, &mutex));
83 ASSERT(step == current + 1);
84 }
7685
77 /* Write lock held. */
7886
79 r = uv_rwlock_tryrdlock(&rwlock);
80 ASSERT(r == UV_EBUSY);
81 r = uv_rwlock_trywrlock(&rwlock);
82 ASSERT(r == UV_EBUSY);
87 static void thread_rwlock_trylock_peer(void* unused) {
88 (void) &unused;
8389
90 uv_mutex_lock(&mutex);
91
92 /* Write lock held by other thread. */
93 ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock));
94 ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
95 synchronize();
96
97 /* Read lock held by other thread. */
98 ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
99 uv_rwlock_rdunlock(&rwlock);
100 ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
101 synchronize();
102
103 /* Acquire write lock. */
104 ASSERT(0 == uv_rwlock_trywrlock(&rwlock));
105 synchronize();
106
107 /* Release write lock and acquire read lock. */
84108 uv_rwlock_wrunlock(&rwlock);
85
86 /* No locks held. */
87
88 r = uv_rwlock_tryrdlock(&rwlock);
89 ASSERT(r == 0);
90
91 /* One read lock held. */
92
93 r = uv_rwlock_tryrdlock(&rwlock);
94 ASSERT(r == 0);
95
96 /* Two read locks held. */
97
98 r = uv_rwlock_trywrlock(&rwlock);
99 ASSERT(r == UV_EBUSY);
109 ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
110 synchronize();
100111
101112 uv_rwlock_rdunlock(&rwlock);
113 synchronize_nowait(); /* Signal main thread we're going away. */
114 uv_mutex_unlock(&mutex);
115 }
102116
103 /* One read lock held. */
104117
118 TEST_IMPL(thread_rwlock_trylock) {
119 uv_thread_t thread;
120
121 ASSERT(0 == uv_cond_init(&condvar));
122 ASSERT(0 == uv_mutex_init(&mutex));
123 ASSERT(0 == uv_rwlock_init(&rwlock));
124
125 uv_mutex_lock(&mutex);
126 ASSERT(0 == uv_thread_create(&thread, thread_rwlock_trylock_peer, NULL));
127
128 /* Hold write lock. */
129 ASSERT(0 == uv_rwlock_trywrlock(&rwlock));
130 synchronize(); /* Releases the mutex to the other thread. */
131
132 /* Release write lock and acquire read lock. Pthreads doesn't support
133 * the notion of upgrading or downgrading rwlocks, so neither do we.
134 */
135 uv_rwlock_wrunlock(&rwlock);
136 ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
137 synchronize();
138
139 /* Release read lock. */
105140 uv_rwlock_rdunlock(&rwlock);
141 synchronize();
106142
107 /* No read locks held. */
143 /* Write lock held by other thread. */
144 ASSERT(UV_EBUSY == uv_rwlock_tryrdlock(&rwlock));
145 ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
146 synchronize();
108147
109 r = uv_rwlock_trywrlock(&rwlock);
110 ASSERT(r == 0);
148 /* Read lock held by other thread. */
149 ASSERT(0 == uv_rwlock_tryrdlock(&rwlock));
150 uv_rwlock_rdunlock(&rwlock);
151 ASSERT(UV_EBUSY == uv_rwlock_trywrlock(&rwlock));
152 synchronize();
111153
112 /* Write lock held. */
113
114 uv_rwlock_wrunlock(&rwlock);
115
116 /* No locks held. */
117
154 ASSERT(0 == uv_thread_join(&thread));
118155 uv_rwlock_destroy(&rwlock);
156 uv_mutex_unlock(&mutex);
157 uv_mutex_destroy(&mutex);
158 uv_cond_destroy(&condvar);
119159
120160 return 0;
121161 }
4141
4242
4343 TEST_IMPL(process_title) {
44 #if defined(__sun)
44 #if defined(__sun) || defined(_AIX)
4545 RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
4646 #else
4747 /* Check for format string vulnerabilities. */
0 /* Copyright The libuv project and contributors. All rights reserved.
1 *
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
3 * of this software and associated documentation files (the "Software"), to
4 * deal in the Software without restriction, including without limitation the
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6 * sell copies of the Software, and to permit persons to whom the Software is
7 * furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18 * IN THE SOFTWARE.
19 */
20
21 #include "uv.h"
22 #include "task.h"
23
24 #include <string.h>
25
26
27 /*
28 * The idea behind the test is as follows.
29 * Certain handle types are stored in a queue internally.
30 * Extra care should be taken for removal of a handle from the queue while iterating over the queue.
31 * (i.e., QUEUE_REMOVE() called within QUEUE_FOREACH())
32 * This usually happens when someone closes or stops a handle from within its callback.
33 * So we need to check that we haven't screwed the queue on close/stop.
34 * To do so we do the following (for each handle type):
35 * 1. Create and start 3 handles (#0, #1, and #2).
36 *
37 * The queue after the start() calls:
38 * ..=> [queue head] <=> [handle] <=> [handle #1] <=> [handle] <=..
39 *
40 * 2. Trigger handles to fire (for uv_idle_t, uv_prepare_t, and uv_check_t there is nothing to do).
41 *
42 * 3. In the callback for the first-executed handle (#0 or #2 depending on handle type)
43 * stop the handle and the next one (#1).
44 * (for uv_idle_t, uv_prepare_t, and uv_check_t callbacks are executed in the reverse order as they are start()'ed,
45 * so callback for handle #2 will be called first)
46 *
47 * The queue after the stop() calls:
48 * correct foreach "next" |
49 * \/
50 * ..=> [queue head] <==============================> [handle] <=..
51 * [ ] <- [handle] <=> [handle #1] -> [ ]
52 * /\
53 * wrong foreach "next" |
54 *
55 * 4. The callback for handle #1 shouldn't be called because the handle #1 is stopped in the previous step.
56 * However, if QUEUE_REMOVE() is not handled properly within QUEUE_FOREACH(), the callback _will_ be called.
57 */
58
59 static const unsigned first_handle_number_idle = 2;
60 static const unsigned first_handle_number_prepare = 2;
61 static const unsigned first_handle_number_check = 2;
62 #ifdef __linux__
63 static const unsigned first_handle_number_fs_event = 0;
64 #endif
65
66
67 #define DEFINE_GLOBALS_AND_CBS(name) \
68 static uv_##name##_t (name)[3]; \
69 static unsigned name##_cb_calls[3]; \
70 \
71 static void name##2_cb(uv_##name##_t* handle) { \
72 ASSERT(handle == &(name)[2]); \
73 if (first_handle_number_##name == 2) { \
74 uv_close((uv_handle_t*)&(name)[2], NULL); \
75 uv_close((uv_handle_t*)&(name)[1], NULL); \
76 } \
77 name##_cb_calls[2]++; \
78 } \
79 \
80 static void name##1_cb(uv_##name##_t* handle) { \
81 ASSERT(handle == &(name)[1]); \
82 ASSERT(0 && "Shouldn't be called" && (&name[0])); \
83 } \
84 \
85 static void name##0_cb(uv_##name##_t* handle) { \
86 ASSERT(handle == &(name)[0]); \
87 if (first_handle_number_##name == 0) { \
88 uv_close((uv_handle_t*)&(name)[0], NULL); \
89 uv_close((uv_handle_t*)&(name)[1], NULL); \
90 } \
91 name##_cb_calls[0]++; \
92 } \
93 \
94 static const uv_##name##_cb name##_cbs[] = { \
95 (uv_##name##_cb)name##0_cb, \
96 (uv_##name##_cb)name##1_cb, \
97 (uv_##name##_cb)name##2_cb, \
98 };
99
100 #define INIT_AND_START(name, loop) \
101 do { \
102 size_t i; \
103 for (i = 0; i < ARRAY_SIZE(name); i++) { \
104 int r; \
105 r = uv_##name##_init((loop), &(name)[i]); \
106 ASSERT(r == 0); \
107 \
108 r = uv_##name##_start(&(name)[i], name##_cbs[i]); \
109 ASSERT(r == 0); \
110 } \
111 } while (0)
112
113 #define END_ASSERTS(name) \
114 do { \
115 ASSERT(name##_cb_calls[0] == 1); \
116 ASSERT(name##_cb_calls[1] == 0); \
117 ASSERT(name##_cb_calls[2] == 1); \
118 } while (0)
119
120 DEFINE_GLOBALS_AND_CBS(idle)
121 DEFINE_GLOBALS_AND_CBS(prepare)
122 DEFINE_GLOBALS_AND_CBS(check)
123
124 #ifdef __linux__
125 DEFINE_GLOBALS_AND_CBS(fs_event)
126
127 static const char watched_dir[] = ".";
128 static uv_timer_t timer;
129 static unsigned helper_timer_cb_calls;
130
131
132 static void init_and_start_fs_events(uv_loop_t* loop) {
133 size_t i;
134 for (i = 0; i < ARRAY_SIZE(fs_event); i++) {
135 int r;
136 r = uv_fs_event_init(loop, &fs_event[i]);
137 ASSERT(r == 0);
138
139 r = uv_fs_event_start(&fs_event[i],
140 (uv_fs_event_cb)fs_event_cbs[i],
141 watched_dir,
142 0);
143 ASSERT(r == 0);
144 }
145 }
146
147 static void helper_timer_cb(uv_timer_t* thandle) {
148 int r;
149 uv_fs_t fs_req;
150
151 /* fire all fs_events */
152 r = uv_fs_utime(thandle->loop, &fs_req, watched_dir, 0, 0, NULL);
153 ASSERT(r == 0);
154 ASSERT(fs_req.result == 0);
155 ASSERT(fs_req.fs_type == UV_FS_UTIME);
156 ASSERT(strcmp(fs_req.path, watched_dir) == 0);
157 uv_fs_req_cleanup(&fs_req);
158
159 helper_timer_cb_calls++;
160 }
161 #endif
162
163
164 TEST_IMPL(queue_foreach_delete) {
165 uv_loop_t* loop;
166 int r;
167
168 loop = uv_default_loop();
169
170 INIT_AND_START(idle, loop);
171 INIT_AND_START(prepare, loop);
172 INIT_AND_START(check, loop);
173
174 #ifdef __linux__
175 init_and_start_fs_events(loop);
176
177 /* helper timer to trigger async and fs_event callbacks */
178 r = uv_timer_init(loop, &timer);
179 ASSERT(r == 0);
180
181 r = uv_timer_start(&timer, helper_timer_cb, 0, 0);
182 ASSERT(r == 0);
183 #endif
184
185 r = uv_run(loop, UV_RUN_NOWAIT);
186 ASSERT(r == 1);
187
188 END_ASSERTS(idle);
189 END_ASSERTS(prepare);
190 END_ASSERTS(check);
191
192 #ifdef __linux__
193 ASSERT(helper_timer_cb_calls == 1);
194 #endif
195
196 MAKE_VALGRIND_HAPPY();
197
198 return 0;
199 }
959959 options.stdio_count = 2;
960960
961961 /* Create a pipe that'll cause a collision. */
962 _snprintf(name,
963 sizeof(name),
964 "\\\\.\\pipe\\uv\\%p-%d",
965 &out,
966 GetCurrentProcessId());
962 snprintf(name,
963 sizeof(name),
964 "\\\\.\\pipe\\uv\\%p-%d",
965 &out,
966 GetCurrentProcessId());
967967 pipe_handle = CreateNamedPipeA(name,
968968 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
969969 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
5757 break;
5858 }
5959 } while (1);
60
61 do {
62 buf = uv_buf_init("", 0);
63 r = uv_try_write((uv_stream_t*) &client, &buf, 1);
64 } while (r != 0);
6065 uv_close((uv_handle_t*) &client, close_cb);
6166 }
6267
4242 r = uv_fileno((uv_handle_t*)sock, &fd);
4343 ASSERT(r == 0);
4444 #ifdef _WIN32
45 r = closesocket(fd);
45 r = closesocket((uv_os_sock_t)fd);
4646 #else
4747 r = close(fd);
4848 #endif
275275
276276 TEST_IMPL(threadpool_cancel_fs) {
277277 struct cancel_info ci;
278 uv_fs_t reqs[25];
278 uv_fs_t reqs[26];
279279 uv_loop_t* loop;
280280 unsigned n;
281281 uv_buf_t iov;
304304 ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, &iov, 1, 0, fs_cb));
305305 ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb));
306306 ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb));
307 ASSERT(0 == uv_fs_realpath(loop, reqs + n++, "/", fs_cb));
307308 ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb));
308309 ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
309310 ASSERT(0 == uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb));
152152 ASSERT(0 == close(fd));
153153 }
154154
155 /* Bug on AIX where '/dev/random' returns 1 from isatty() */
156 #ifndef _AIX
155157 fd = open("/dev/random", O_RDONLY);
156158 if (fd != -1) {
157159 ASSERT(UV_EINVAL == uv_tty_init(&loop, &tty, fd, 1));
158160 ASSERT(0 == close(fd));
159161 }
162 #endif /* _AIX */
160163
161164 fd = open("/dev/zero", O_RDONLY);
162165 if (fd != -1) {
2525 #include <stdlib.h>
2626 #include <string.h>
2727
28 #ifdef __FreeBSD__
29 #include <sys/sysctl.h>
30 #endif
31
2832 #define CHECK_HANDLE(handle) \
2933 ASSERT((uv_udp_t*)(handle) == &server \
3034 || (uv_udp_t*)(handle) == &client \
4145 static int send_cb_called;
4246 static int recv_cb_called;
4347 static int close_cb_called;
48
49 #ifdef __FreeBSD__
50 static int can_ipv6_ipv4_dual() {
51 int v6only;
52 size_t size = sizeof(int);
53
54 if (sysctlbyname("net.inet6.ip6.v6only", &v6only, &size, NULL, 0))
55 return 0;
56
57 return v6only != 1;
58 }
59 #endif
4460
4561
4662 static void alloc_cb(uv_handle_t* handle,
149165 if (!can_ipv6())
150166 RETURN_SKIP("IPv6 not supported");
151167
168 #ifdef __FreeBSD__
169 if (!can_ipv6_ipv4_dual())
170 RETURN_SKIP("IPv6-IPv4 dual stack not supported");
171 #endif
172
152173 do_test(ipv6_recv_ok, 0);
153174
154175 ASSERT(recv_cb_called == 1);
118118 ASSERT(r == 0);
119119
120120 /* join the multicast channel */
121 #if defined(__APPLE__)
121 #if defined(__APPLE__) || defined(_AIX)
122122 r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP);
123123 #else
124124 r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP);
102102 'src/win/winapi.h',
103103 'src/win/winsock.c',
104104 'src/win/winsock.h',
105 ],
106 'conditions': [
107 ['MSVS_VERSION < "2015"', {
108 'sources': [
109 'src/win/snprintf.c'
110 ]
111 }]
105112 ],
106113 'link_settings': {
107114 'libraries': [
339346 'test/test-poll-close-doesnt-corrupt-stack.c',
340347 'test/test-poll-closesocket.c',
341348 'test/test-process-title.c',
349 'test/test-queue-foreach-delete.c',
342350 'test/test-ref.c',
343351 'test/test-run-nowait.c',
344352 'test/test-run-once.c',