Commit 4805d78f authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #1254 from gevent/libuv1.21

Update to libuv 1.22
parents e15dc9ea 256a3fbf
......@@ -7,6 +7,8 @@
1.3.5 (unreleased)
==================
- Update the bundled libuv from 1.20.1 to 1.22.0.
- Update Python versions tested on Travis, including PyPy to 6.0. See :issue:`1195`.
- :mod:`gevent.queue` imports ``_PySimpleQueue`` instead of
......
......@@ -336,3 +336,12 @@ Bob Burger <rgburger@beckman.com>
Thomas Versteeg <thomasversteeg@gmx.com>
zzzjim <zzzjim@users.noreply.github.com>
Alex Arslan <ararslan@comcast.net>
Kyle Farnung <kfarnung@microsoft.com>
ssrlive <30760636+ssrlive@users.noreply.github.com>
Tobias Nießen <tniessen@tnie.de>
Björn Linse <bjorn.linse@gmail.com>
zyxwvu Shi <i@shiyc.cn>
Peter Johnson <johnson.peter@gmail.com>
Paolo Greppi <paolo.greppi@libpf.com>
Shelley Vohr <shelley.vohr@gmail.com>
Ujjwal Sharma <usharma1998@gmail.com>
This diff is collapsed.
......@@ -137,7 +137,10 @@ $ git rebase upstream/v1.x # or upstream/master
### TEST
Bug fixes and features should come with tests. Add your tests in the
`test/` directory. Each new test needs to be registered in `test/test-list.h`. If you add a new test file, it needs to be registered in two places:
`test/` directory. Each new test needs to be registered in `test/test-list.h`.
If you add a new test file, it needs to be registered in three places:
- `CMakeLists.txt`: add the file's name to the `uv_test_sources` list.
- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list.
- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target.
......
2018.04.19, Version 1.20.1 (Stable)
2018.07.11, Version 1.22.0 (Stable)
Changes since version 1.21.0:
* unix: remove checksparse.sh (Ben Noordhuis)
* win: fix mingw build error (Ben Noordhuis)
* win: fix -Wunused-function warnings in thread.c (Ben Noordhuis)
* unix,win: merge timers implementation (Ben Noordhuis)
* win: fix pointer type in pipe.c (Ben Noordhuis)
* win: fixing build for older MSVC compilers (Michael Fero)
* zos: clear poll events on every iteration (jBarz)
* zos: write-protect message queue (jBarz)
* zos: use correct pointer type in strnlen (jBarz)
* unix,win: merge handle flags (Ben Noordhuis)
* doc: update Imran Iqbal's GitHub handle (cjihrig)
* src: add new error apis to prevent memory leaks (Shelley Vohr)
* test: make test-condvar call uv_cond_wait (Jamie Davis)
* fs: change position of uv_fs_lchown (Ujjwal Sharma)
2018.06.23, Version 1.21.0 (Stable), e4983a9b0c152932f7553ff4a9ff189d2314cdcb
Changes since version 1.20.3:
* unix,windows: map EFTYPE errno (cjihrig)
* win: perform case insensitive PATH= comparison (cjihrig)
* win, fs: uv_fs_fchmod support for -A files (Bartosz Sosnowski)
* src,lib: fix comments (Tobias Nießen)
* win,process: allow child pipe handles to be opened in overlapped mode (Björn
Linse)
* src,test: fix idiosyncratic comment style (Bert Belder)
* test: fs_fchmod_archive_readonly must return a value (Bert Belder)
* win,pipe: fix incorrect error code returned from uv_pipe_write_impl() (Bert
Belder)
* win,pipe: properly set uv_write_t.send_handle in uv_write2() (Bert Belder)
* test: add vectored uv_write() ping-pong tests (Bert Belder)
* win,pipe: support vectored uv_write() calls (Bert Belder)
* win,pipe: refactor pipe read cancellation logic (Bert Belder)
* test: improve output from IPC test helpers (Bert Belder)
* test: add test for IPC deadlock on Windows (
* win,pipe: fix IPC pipe deadlock (Bert Belder)
* unix: catch some cases of watching fd twice (Ben Noordhuis)
* test: use custom timeout for getaddrinfo_fail_sync (Ben Noordhuis)
* Revert "win: add Windows XP support to uv_if_indextoname()" (Bert Belder)
* win,thread: remove fallback uv_cond implementation (Bert Belder)
* src,test: s/olny/only (cjihrig)
* unix: close signal pipe fds on unload (Ben Noordhuis)
* win: allow setting udp socket options before bind (cjihrig)
* unix: return UV_ENOTSUP on FICLONE_FORCE failure (cjihrig)
* win,pipe: remove unreferenced local variable (Bert Belder)
* win,code: remove GetQueuedCompletionStatus-based poller (Bert Belder)
* win: remove the remaining dynamic kernel32 imports (Bert Belder)
* test: speedup process-title-threadsafe on macOS (cjihrig)
* core: move all include files except uv.h to uv/ (Saúl Ibarra Corretgé)
* win: move stdint-msvc2008.h to include/uv/ (Ben Noordhuis)
* build: fix cygwin install (Ben Noordhuis)
* build,win: remove MinGW Makefile (Saúl Ibarra Corretgé)
* build: add a cmake build file (Ben Noordhuis)
* build: add test suite option to cmake build (Ben Noordhuis)
* unix: set errno in uv_fs_copyfile() (cjihrig)
* samples: fix inconsistency in parse_opts vs usage (zyxwvu Shi)
* linux: handle exclusive POLLHUP with UV_DISCONNECT (Brad King)
* include: declare uv_cpu_times_s in higher scope (Peter Johnson)
* doc: add uv_fs_fsync() AIX limitations (jBarz)
* unix,win: add uv_fs_lchown() (Paolo Greppi)
* unix: disable clang variable length array warning (Peter Johnson)
* doc: document uv_pipe_t::ipc (Ed Schouten)
* doc: undocument uv_req_type's UV_REQ_TYPE_PRIVATE (Ed Schouten)
* doc: document UV_*_MAP() macros (Ed Schouten)
* win: remove use of min() macro in pipe.c (Peter Johnson)
* doc: add jbarz as maintainer (
2018.05.08, Version 1.20.3 (Stable), 8cfd67e59195251dff793ee47c185c9d6a8f3818
Changes since version 1.20.2:
* win: add Windows XP support to uv_if_indextoname() (ssrlive)
* win: fix `'floor' undefined` compiler warning (ssrlive)
* win, pipe: stop read for overlapped pipe (Bartosz Sosnowski)
* build: fix utf-8 name of copyright holder (Jérémy Lal)
* zos: initialize pollfd revents (jBarz)
* zos,doc: add system V message queue note (jBarz)
* linux: don't use uv__nonblock_ioctl() on sparc (Ben Noordhuis)
2018.04.23, Version 1.20.2 (Stable), c51fd3f66bbb386a1efdeba6812789f35a372d1e
Changes since version 1.20.1:
* zos: use custom semaphore (jBarz)
* win: fix registry API error handling (Kyle Farnung)
* build: add support for 64-bit AIX (Richard Lau)
* aix: guard STATIC_ASSERT for glibc work around (Richard Lau)
2018.04.19, Version 1.20.1 (Stable), 36ac2fc8edfd5ff3e9be529be1d4a3f0d5364e94
Changes since version 1.20.0:
......
......@@ -12,8 +12,9 @@ libuv is currently managed by the following individuals:
- GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb)
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
* **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere))
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
* **John Barboza** ([@jbarz](https://github.com/jbarz))
* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno))
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
......
......@@ -17,7 +17,10 @@ ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_srcdir)/src
include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h
include_HEADERS=include/uv.h
uvincludedir = $(includedir)/uv
uvinclude_HEADERS=include/uv/errno.h include/uv/threadpool.h include/uv/version.h
CLEANFILES =
......@@ -29,6 +32,7 @@ libuv_la_SOURCES = src/fs-poll.c \
src/inet.c \
src/queue.h \
src/threadpool.c \
src/timer.c \
src/uv-data-getter-setters.c \
src/uv-common.c \
src/uv-common.h \
......@@ -42,7 +46,7 @@ endif
if WINNT
include_HEADERS += include/uv-win.h include/tree.h
uvinclude_HEADERS += include/uv/win.h include/uv/tree.h
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
-DWIN32_LEAN_AND_MEAN \
-D_WIN32_WINNT=0x0600
......@@ -71,7 +75,6 @@ libuv_la_SOURCES += src/win/async.c \
src/win/stream-inl.h \
src/win/tcp.c \
src/win/thread.c \
src/win/timer.c \
src/win/tty.c \
src/win/udp.c \
src/win/util.c \
......@@ -82,7 +85,7 @@ libuv_la_SOURCES += src/win/async.c \
else # WINNT
include_HEADERS += include/uv-unix.h
uvinclude_HEADERS += include/uv/unix.h
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
libuv_la_SOURCES += src/unix/async.c \
src/unix/atomic-ops.h \
......@@ -102,7 +105,6 @@ libuv_la_SOURCES += src/unix/async.c \
src/unix/stream.c \
src/unix/tcp.c \
src/unix/thread.c \
src/unix/timer.c \
src/unix/tty.c \
src/unix/udp.c
......@@ -121,7 +123,6 @@ EXTRA_DIST = test/fixtures/empty_file \
README.md \
checksparse.sh \
vcbuild.bat \
Makefile.mingw \
common.gypi \
gyp_uv.py \
uv.gyp
......@@ -191,6 +192,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-idle.c \
test/test-ip4-addr.c \
test/test-ip6-addr.c \
test/test-ipc-heavy-traffic-deadlock-bug.c \
test/test-ipc-send-recv.c \
test/test-ipc.c \
test/test-list.h \
......@@ -332,19 +334,19 @@ libuv_la_CFLAGS += -D_ALL_SOURCE \
-D_LINUX_SOURCE_COMPAT \
-D_THREAD_SAFE \
-DHAVE_SYS_AHAFS_EVPRODS_H
include_HEADERS += include/uv-aix.h
uvinclude_HEADERS += include/uv/aix.h
libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c
endif
if ANDROID
include_HEADERS += include/android-ifaddrs.h \
include/pthread-barrier.h
uvinclude_HEADERS += include/uv/android-ifaddrs.h \
include/uv/pthread-barrier.h
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
src/unix/pthread-fixes.c
endif
if CYGWIN
include_HEADERS += include/uv-posix.h
uvinclude_HEADERS += include/uv/posix.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/cygwin.c \
src/unix/bsd-ifaddrs.c \
......@@ -358,8 +360,8 @@ libuv_la_SOURCES += src/unix/cygwin.c \
endif
if DARWIN
include_HEADERS += include/uv-darwin.h \
include/pthread-barrier.h
uvinclude_HEADERS += include/uv/darwin.h \
include/uv/pthread-barrier.h
libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
......@@ -372,7 +374,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if DRAGONFLY
include_HEADERS += include/uv-bsd.h
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
......@@ -381,7 +383,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if FREEBSD
include_HEADERS += include/uv-bsd.h
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/freebsd.c \
src/unix/kqueue.c \
......@@ -390,7 +392,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if LINUX
include_HEADERS += include/uv-linux.h
uvinclude_HEADERS += include/uv/linux.h
libuv_la_CFLAGS += -D_GNU_SOURCE
libuv_la_SOURCES += src/unix/linux-core.c \
src/unix/linux-inotify.c \
......@@ -417,7 +419,7 @@ libuv_la_SOURCES += src/unix/cygwin.c \
endif
if NETBSD
include_HEADERS += include/uv-bsd.h
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/kqueue.c \
src/unix/netbsd.c \
......@@ -426,7 +428,7 @@ test_run_tests_LDFLAGS += -lutil
endif
if OPENBSD
include_HEADERS += include/uv-bsd.h
uvinclude_HEADERS += include/uv/bsd.h
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
src/unix/kqueue.c \
src/unix/openbsd.c \
......@@ -435,14 +437,14 @@ test_run_tests_LDFLAGS += -lutil
endif
if SUNOS
include_HEADERS += include/uv-sunos.h
uvinclude_HEADERS += include/uv/sunos.h
libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
libuv_la_SOURCES += src/unix/no-proctitle.c \
src/unix/sunos.c
endif
if OS390
include_HEADERS += include/pthread-barrier.h
uvinclude_HEADERS += include/uv/pthread-barrier.h
libuv_la_CFLAGS += -D_UNIX03_THREADS \
-D_UNIX03_SOURCE \
-D_OPEN_SYS_IF_EXT=1 \
......
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
CC ?= gcc
CFLAGS += -Wall \
-Wextra \
-Wno-unused-parameter \
-Wstrict-prototypes \
-Iinclude \
-Isrc \
-Isrc/win \
-DWIN32_LEAN_AND_MEAN \
-D_WIN32_WINNT=0x0600
INCLUDES = include/stdint-msvc2008.h \
include/tree.h \
include/uv-errno.h \
include/uv-threadpool.h \
include/uv-version.h \
include/uv-win.h \
include/uv.h \
src/heap-inl.h \
src/queue.h \
src/uv-common.h \
src/win/atomicops-inl.h \
src/win/handle-inl.h \
src/win/internal.h \
src/win/req-inl.h \
src/win/stream-inl.h \
src/win/winapi.h \
src/win/winsock.h
OBJS = src/fs-poll.o \
src/inet.o \
src/threadpool.o \
src/uv-common.o \
src/version.o \
src/win/async.o \
src/win/core.o \
src/win/detect-wakeup.o \
src/win/dl.o \
src/win/error.o \
src/win/fs-event.o \
src/win/fs.o \
src/win/getaddrinfo.o \
src/win/getnameinfo.o \
src/win/handle.o \
src/win/loop-watcher.o \
src/win/pipe.o \
src/win/poll.o \
src/win/process-stdio.o \
src/win/process.o \
src/win/req.o \
src/win/signal.o \
src/win/stream.o \
src/win/tcp.o \
src/win/thread.o \
src/win/timer.o \
src/win/tty.o \
src/win/udp.o \
src/win/util.o \
src/win/winapi.o \
src/win/winsock.o
all: libuv.a
clean:
-$(RM) $(OBJS) libuv.a
libuv.a: $(OBJS)
$(AR) crs $@ $^
$(OBJS): %.o : %.c $(INCLUDES)
$(CC) $(CFLAGS) -c -o $@ $<
......@@ -169,6 +169,16 @@ $ make check
$ make install
```
To build with [CMake](https://cmake.org/):
```bash
$ mkdir -p out/cmake ; cd out/cmake ; cmake -DBUILD_TESTING=ON ../..
$ make all test
# Or manually:
$ ./uv_run_tests # shared library build
$ ./uv_run_tests_a # static library build
```
To build with GYP, first run:
```bash
......@@ -322,6 +332,13 @@ describes the package in more detail.
AIX support for filesystem events is not compiled when building with `gyp`.
### z/OS Notes
z/OS creates System V semaphores and message queues. These persist on the system
after the process terminates unless the event loop is closed.
Use the `ipcrm` command to manually clear up System V resources.
## Patches
See the [guidelines for contributing][].
......
#!/bin/sh
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
SPARSE=${SPARSE:-sparse}
SPARSE_FLAGS=${SPARSE_FLAGS:-"
-D__POSIX__
-Wsparse-all
-Wno-do-while
-Wno-transparent-union
-Iinclude
-Isrc
"}
SOURCES="
include/tree.h
include/uv-unix.h
include/uv.h
src/fs-poll.c
src/inet.c
src/queue.h
src/unix/async.c
src/unix/core.c
src/unix/dl.c
src/unix/fs.c
src/unix/getaddrinfo.c
src/unix/internal.h
src/unix/loop-watcher.c
src/unix/loop.c
src/unix/pipe.c
src/unix/poll.c
src/unix/process.c
src/unix/signal.c
src/unix/stream.c
src/unix/tcp.c
src/unix/thread.c
src/unix/threadpool.c
src/unix/timer.c
src/unix/tty.c
src/unix/udp.c
src/uv-common.c
src/uv-common.h
src/uv-data-getter-setters.c
"
TESTS="
test/benchmark-async-pummel.c
test/benchmark-async.c
test/benchmark-fs-stat.c
test/benchmark-getaddrinfo.c
test/benchmark-loop-count.c
test/benchmark-million-async.c
test/benchmark-million-timers.c
test/benchmark-multi-accept.c
test/benchmark-ping-pongs.c
test/benchmark-pound.c
test/benchmark-pump.c
test/benchmark-sizes.c
test/benchmark-spawn.c
test/benchmark-tcp-write-batch.c
test/benchmark-thread.c
test/benchmark-udp-pummel.c
test/blackhole-server.c
test/dns-server.c
test/echo-server.c
test/run-benchmarks.c
test/run-tests.c
test/runner-unix.c
test/runner-unix.h
test/runner.c
test/runner.h
test/task.h
test/test-active.c
test/test-async.c
test/test-barrier.c
test/test-callback-order.c
test/test-callback-stack.c
test/test-condvar.c
test/test-connection-fail.c
test/test-cwd-and-chdir.c
test/test-delayed-accept.c
test/test-dlerror.c
test/test-embed.c
test/test-env-vars.c
test/test-error.c
test/test-fail-always.c
test/test-fs-copyfile.c
test/test-fs-event.c
test/test-fs-poll.c
test/test-fs.c
test/test-getters-setters.c
test/test-get-currentexe.c
test/test-get-loadavg.c
test/test-get-memory.c
test/test-get-passwd.c
test/test-getaddrinfo.c
test/test-gethostname.c
test/test-getsockname.c
test/test-homedir.c
test/test-hrtime.c
test/test-idle.c
test/test-ip6-addr.c
test/test-ipc-send-recv.c
test/test-ipc.c
test/test-loop-handles.c
test/test-multiple-listen.c
test/test-mutexes.c
test/test-pass-always.c
test/test-ping-pong.c
test/test-pipe-bind-error.c
test/test-pipe-connect-error.c
test/test-pipe-sendmsg.c
test/test-pipe-server-close.c
test/test-platform-output.c
test/test-poll-close.c
test/test-poll.c
test/test-process-title.c
test/test-process-title-threadsafe.c
test/test-ref.c
test/test-run-nowait.c
test/test-run-once.c
test/test-semaphore.c
test/test-shutdown-close.c
test/test-shutdown-eof.c
test/test-signal-multiple-loops.c
test/test-signal.c
test/test-spawn.c
test/test-stdio-over-pipes.c
test/test-tcp-bind-error.c
test/test-tcp-bind6-error.c
test/test-tcp-close-while-connecting.c
test/test-tcp-close-accept.c
test/test-tcp-close.c
test/test-tcp-connect-error-after-write.c
test/test-tcp-connect-error.c
test/test-tcp-connect-timeout.c
test/test-tcp-connect6-error.c
test/test-tcp-flags.c
test/test-tcp-open.c
test/test-tcp-read-stop.c
test/test-tcp-shutdown-after-write.c
test/test-tcp-unexpected-read.c
test/test-tcp-oob.c
test/test-tcp-write-error.c
test/test-tcp-write-to-half-open-connection.c
test/test-tcp-writealot.c
test/test-thread.c
test/test-threadpool-cancel.c
test/test-threadpool.c
test/test-timer-again.c
test/test-timer.c
test/test-tmpdir.c
test/test-tty.c
test/test-udp-dgram-too-big.c
test/test-udp-ipv6.c
test/test-udp-multicast-join.c
test/test-udp-multicast-ttl.c
test/test-udp-open.c
test/test-udp-options.c
test/test-udp-send-and-recv.c
test/test-udp-send-hang-loop.c
test/test-walk-handles.c
test/test-watcher-cross-stop.c
"
case `uname -s` in
AIX)
SPARSE_FLAGS="$SPARSE_FLAGS -D_AIX=1"
SOURCES="$SOURCES
src/unix/aix-common.c
src/unix/aix.c"
;;
OS400)
SPARSE_FLAGS="$SPARSE_FLAGS -D__PASE__=1"
SOURCES="$SOURCES
src/unix/aix-common.c
src/unix/ibmi.c
src/unix/posix-poll.c
src/unix/no-fsevents.c
src/unix/no-proctitle.c"
;;
Darwin)
SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1"
SOURCES="$SOURCES
include/uv-bsd.h
src/unix/darwin.c
src/unix/kqueue.c
src/unix/fsevents.c"
;;
DragonFly)
SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1"
SOURCES="$SOURCES
include/uv-bsd.h
src/unix/kqueue.c
src/unix/freebsd.c"
;;
FreeBSD)
SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1"
SOURCES="$SOURCES
include/uv-bsd.h
src/unix/kqueue.c
src/unix/freebsd.c"
;;
Linux)
SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1"
SOURCES="$SOURCES
include/uv-linux.h
src/unix/linux-inotify.c
src/unix/linux-core.c
src/unix/linux-syscalls.c
src/unix/linux-syscalls.h"
;;
NetBSD)
SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1"
SOURCES="$SOURCES
include/uv-bsd.h
src/unix/kqueue.c
src/unix/netbsd.c"
;;
OpenBSD)
SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1"
SOURCES="$SOURCES
include/uv-bsd.h
src/unix/kqueue.c
src/unix/openbsd.c"
;;
SunOS)
SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1"
SOURCES="$SOURCES
include/uv-sunos.h
src/unix/sunos.c"
;;
esac
for ARCH in __i386__ __x86_64__ __arm__ __mips__; do
$SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES
done
# Tests are architecture independent.
$SPARSE $SPARSE_FLAGS -Itest $TESTS
......@@ -134,7 +134,7 @@
}]
]
}],
['OS in "freebsd dragonflybsd linux openbsd solaris android"', {
['OS in "freebsd dragonflybsd linux openbsd solaris android aix"', {
'cflags': [ '-Wall' ],
'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
'target_conditions': [
......@@ -162,6 +162,10 @@
'cflags': [ '-pthread' ],
'ldflags': [ '-pthread' ],
}],
[ 'OS=="aix" and target_arch=="ppc64"', {
'cflags': [ '-maix64' ],
'ldflags': [ '-maix64' ],
}],
],
}],
['OS=="mac"', {
......
......@@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.20.1], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.22.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
......
......@@ -45,21 +45,21 @@ extern "C" {
# define UV_EXTERN /* nothing */
#endif
#include "uv-errno.h"
#include "uv-version.h"
#include "uv/errno.h"
#include "uv/version.h"
#include <stddef.h>
#include <stdio.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
#if defined(_WIN32)
# include "uv-win.h"
# include "uv/win.h"
#else
# include "uv-unix.h"
# include "uv/unix.h"
#endif
/* Expand this list if necessary. */
......@@ -142,6 +142,7 @@ extern "C" {
XX(EHOSTDOWN, "host is down") \
XX(EREMOTEIO, "remote I/O error") \
XX(ENOTTY, "inappropriate ioctl for device") \
XX(EFTYPE, "inappropriate file type or format") \
#define UV_HANDLE_TYPE_MAP(XX) \
XX(ASYNC, async) \
......@@ -369,7 +370,10 @@ typedef enum {
UV_EXTERN int uv_translate_sys_error(int sys_errno);
UV_EXTERN const char* uv_strerror(int err);
UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen);
UV_EXTERN const char* uv_err_name(int err);
UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);
#define UV_REQ_FIELDS \
......@@ -503,7 +507,7 @@ UV_EXTERN int uv_try_write(uv_stream_t* handle,
struct uv_write_s {
UV_REQ_FIELDS
uv_write_cb cb;
uv_stream_t* send_handle;
uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */
uv_stream_t* handle;
UV_WRITE_PRIVATE_FIELDS
};
......@@ -865,7 +869,13 @@ typedef enum {
* flags may be specified to create a duplex data stream.
*/
UV_READABLE_PIPE = 0x10,
UV_WRITABLE_PIPE = 0x20
UV_WRITABLE_PIPE = 0x20,
/*
* Open the child pipe handle in overlapped mode on Windows.
* On Unix it is silently ignored.
*/
UV_OVERLAPPED_PIPE = 0x40
} uv_stdio_flags;
typedef struct uv_stdio_container_s {
......@@ -997,16 +1007,18 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop,
UV_EXTERN int uv_cancel(uv_req_t* req);
struct uv_cpu_times_s {
uint64_t user;
uint64_t nice;
uint64_t sys;
uint64_t idle;
uint64_t irq;
};
struct uv_cpu_info_s {
char* model;
int speed;
struct uv_cpu_times_s {
uint64_t user;
uint64_t nice;
uint64_t sys;
uint64_t idle;
uint64_t irq;
} cpu_times;
struct uv_cpu_times_s cpu_times;
};
struct uv_interface_address_s {
......@@ -1133,7 +1145,8 @@ typedef enum {
UV_FS_CHOWN,
UV_FS_FCHOWN,
UV_FS_REALPATH,
UV_FS_COPYFILE
UV_FS_COPYFILE,
UV_FS_LCHOWN
} uv_fs_type;
/* uv_fs_t is a subclass of uv_req_t. */
......@@ -1336,6 +1349,12 @@ UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,
uv_uid_t uid,
uv_gid_t gid,
uv_fs_cb cb);
UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
uv_uid_t uid,
uv_gid_t gid,
uv_fs_cb cb);
enum uv_fs_event {
......
......@@ -433,5 +433,11 @@
# define UV__ENOTTY (-4029)
#endif
#if defined(EFTYPE) && !defined(_WIN32)
# define UV__EFTYPE UV__ERR(EFTYPE)
#else
# define UV__EFTYPE (-4028)
#endif
#endif /* UV_ERRNO_H_ */
......@@ -22,7 +22,7 @@
#ifndef UV_MVS_H
#define UV_MVS_H
#define UV_PLATFORM_SEM_T int
#define UV_PLATFORM_SEM_T long
#define UV_PLATFORM_LOOP_FIELDS \
void* ep; \
......
......@@ -42,32 +42,32 @@
#include <pthread.h>
#include <signal.h>
#include "uv-threadpool.h"
#include "uv/threadpool.h"
#if defined(__linux__)
# include "uv-linux.h"
# include "uv/linux.h"
#elif defined (__MVS__)
# include "uv-os390.h"
# include "uv/os390.h"
#elif defined(__PASE__)
# include "uv-posix.h"
# include "uv/posix.h"
#elif defined(_AIX)
# include "uv-aix.h"
# include "uv/aix.h"
#elif defined(__sun)
# include "uv-sunos.h"
# include "uv/sunos.h"
#elif defined(__APPLE__)
# include "uv-darwin.h"
# include "uv/darwin.h"
#elif defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# include "uv-bsd.h"
# include "uv/bsd.h"
#elif defined(__CYGWIN__) || defined(__MSYS__)
# include "uv-posix.h"
# include "uv/posix.h"
#endif
#ifndef PTHREAD_BARRIER_SERIAL_THREAD
# include "pthread-barrier.h"
# include "uv/pthread-barrier.h"
#endif
#ifndef NI_MAXHOST
......
......@@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 20
#define UV_VERSION_PATCH 1
#define UV_VERSION_MINOR 22
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
......
......@@ -53,13 +53,13 @@ typedef struct pollfd {
#include <sys/stat.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
#include "tree.h"
#include "uv-threadpool.h"
#include "uv/tree.h"
#include "uv/threadpool.h"
#define MAX_PIPENAME_LEN 256
......@@ -86,8 +86,8 @@ typedef struct pollfd {
#define SIGKILL 9
#define SIGWINCH 28
/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */
/* unix-like platforms. However MinGW doesn't define it, so we do. */
/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like
* platforms. However MinGW doesn't define it, so we do. */
#ifndef SIGABRT_COMPAT
# define SIGABRT_COMPAT 6
#endif
......@@ -244,7 +244,7 @@ typedef union {
CRITICAL_SECTION waiters_count_lock;
HANDLE signal_event;
HANDLE broadcast_event;
} fallback;
} unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
} uv_cond_t;
typedef union {
......@@ -308,8 +308,6 @@ typedef struct {
char* errmsg;
} uv_lib_t;
RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define UV_LOOP_PRIVATE_FIELDS \
/* The loop's I/O completion port */ \
HANDLE iocp; \
......@@ -321,8 +319,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
uv_req_t* pending_reqs_tail; \
/* Head of a single-linked list of closed handles */ \
uv_handle_t* endgame_handles; \
/* The head of the timers tree */ \
struct uv_timer_tree_s timers; \
/* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */ \
void* timer_heap; \
/* Lists of active loop (prepare / check / idle) watchers */ \
uv_prepare_t* prepare_handles; \
uv_check_t* check_handles; \
......@@ -368,10 +366,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
} u; \
struct uv_req_s* next_req;
#define UV_WRITE_PRIVATE_FIELDS \
int ipc_header; \
uv_buf_t write_buffer; \
HANDLE event_handle; \
#define UV_WRITE_PRIVATE_FIELDS \
int coalesced; \
uv_buf_t write_buffer; \
HANDLE event_handle; \
HANDLE wait_handle;
#define UV_CONNECT_PRIVATE_FIELDS \
......@@ -459,16 +457,17 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#define uv_pipe_connection_fields \
uv_timer_t* eof_timer; \
uv_write_t ipc_header_write_req; \
int ipc_pid; \
uint64_t remaining_ipc_rawdata_bytes; \
struct { \
void* queue[2]; \
int queue_len; \
} pending_ipc_info; \
uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
DWORD ipc_remote_pid; \
union { \
uint32_t payload_remaining; \
uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
} ipc_data_frame; \
void* ipc_xfer_queue[2]; \
int ipc_xfer_queue_length; \
uv_write_t* non_overlapped_writes_tail; \
uv_mutex_t readfile_mutex; \
volatile HANDLE readfile_thread;
CRITICAL_SECTION readfile_thread_lock; \
volatile HANDLE readfile_thread_handle;
#define UV_PIPE_PRIVATE_FIELDS \
HANDLE handle; \
......@@ -478,8 +477,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
struct { uv_pipe_connection_fields } conn; \
} pipe;
/* TODO: put the parser states in an union - TTY handles are always */
/* half-duplex so read-state can safely overlap write-state. */
/* TODO: put the parser states in an union - TTY handles are always half-duplex
* so read-state can safely overlap write-state. */
#define UV_TTY_PRIVATE_FIELDS \
HANDLE handle; \
union { \
......@@ -528,8 +527,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
unsigned char events;
#define UV_TIMER_PRIVATE_FIELDS \
RB_ENTRY(uv_timer_s) tree_entry; \
uint64_t due; \
void* heap_node[3]; \
int unused; \
uint64_t timeout; \
uint64_t repeat; \
uint64_t start_id; \
uv_timer_cb timer_cb;
......
......@@ -3,7 +3,7 @@ exec_prefix=${prefix}
libdir=@libdir@
includedir=@includedir@
Name: @PACKAGE_NAME@
Name: libuv
Version: @PACKAGE_VERSION@
Description: multi-platform support library with a focus on asynchronous I/O.
URL: http://libuv.org/
......
dnl Macros to check the presence of generic (non-typed) symbols.
dnl Copyright (c) 2006-2008 Diego Pettenà <flameeyes gmail com>
dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes gmail com>
dnl Copyright (c) 2006-2008 xine project
dnl
dnl This program is free software; you can redistribute it and/or modify
......@@ -316,4 +316,4 @@ AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
[Define the highest alignment supported])
fi
])
\ No newline at end of file
])
......@@ -83,7 +83,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle,
if (err < 0)
goto error;
ctx->timer_handle.flags |= UV__HANDLE_INTERNAL;
ctx->timer_handle.flags |= UV_HANDLE_INTERNAL;
uv__handle_unref(&ctx->timer_handle);
err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);
......@@ -248,7 +248,7 @@ static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) {
#include "win/handle-inl.h"
void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
assert(handle->flags & UV__HANDLE_CLOSING);
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
uv__handle_close(handle);
}
......
......@@ -19,7 +19,7 @@
#include <string.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
......
......@@ -19,13 +19,22 @@
*/
#include "uv.h"
#include "internal.h"
#include "uv-common.h"
#include "heap-inl.h"
#include <assert.h>
#include <limits.h>
static struct heap *timer_heap(const uv_loop_t* loop) {
#ifdef _WIN32
return (struct heap*) loop->timer_heap;
#else
return (struct heap*) &loop->timer_heap;
#endif
}
static int timer_less_than(const struct heap_node* ha,
const struct heap_node* hb) {
const uv_timer_t* a;
......@@ -81,7 +90,7 @@ int uv_timer_start(uv_timer_t* handle,
/* start_id is the second index to be compared in uv__timer_cmp() */
handle->start_id = handle->loop->timer_counter++;
heap_insert((struct heap*) &handle->loop->timer_heap,
heap_insert(timer_heap(handle->loop),
(struct heap_node*) &handle->heap_node,
timer_less_than);
uv__handle_start(handle);
......@@ -94,7 +103,7 @@ int uv_timer_stop(uv_timer_t* handle) {
if (!uv__is_active(handle))
return 0;
heap_remove((struct heap*) &handle->loop->timer_heap,
heap_remove(timer_heap(handle->loop),
(struct heap_node*) &handle->heap_node,
timer_less_than);
uv__handle_stop(handle);
......@@ -131,7 +140,7 @@ int uv__next_timeout(const uv_loop_t* loop) {
const uv_timer_t* handle;
uint64_t diff;
heap_node = heap_min((const struct heap*) &loop->timer_heap);
heap_node = heap_min(timer_heap(loop));
if (heap_node == NULL)
return -1; /* block indefinitely */
......@@ -152,7 +161,7 @@ void uv__run_timers(uv_loop_t* loop) {
uv_timer_t* handle;
for (;;) {
heap_node = heap_min((struct heap*) &loop->timer_heap);
heap_node = heap_min(timer_heap(loop));
if (heap_node == NULL)
break;
......
......@@ -23,7 +23,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "android-ifaddrs.h"
#include "uv/android-ifaddrs.h"
#include "uv-common.h"
#include <string.h>
......
......@@ -116,7 +116,7 @@ uint64_t uv_hrtime(void) {
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
assert(!uv__is_closing(handle));
handle->flags |= UV_CLOSING;
handle->flags |= UV_HANDLE_CLOSING;
handle->close_cb = close_cb;
switch (handle->type) {
......@@ -174,8 +174,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_SIGNAL:
uv__signal_close((uv_signal_t*) handle);
/* Signal handles may not be closed immediately. The signal code will */
/* itself close uv__make_close_pending whenever appropriate. */
/* Signal handles may not be closed immediately. The signal code will
* itself close uv__make_close_pending whenever appropriate. */
return;
default:
......@@ -214,8 +214,8 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
}
void uv__make_close_pending(uv_handle_t* handle) {
assert(handle->flags & UV_CLOSING);
assert(!(handle->flags & UV_CLOSED));
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->next_closing = handle->loop->closing_handles;
handle->loop->closing_handles = handle;
}
......@@ -241,15 +241,17 @@ int uv__getiovmax(void) {
static void uv__finish_close(uv_handle_t* handle) {
/* Note: while the handle is in the UV_CLOSING state now, it's still possible
* for it to be active in the sense that uv__is_active() returns true.
/* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
* possible for it to be active in the sense that uv__is_active() returns
* true.
*
* A good example is when the user calls uv_shutdown(), immediately followed
* by uv_close(). The handle is considered active at this point because the
* completion of the shutdown req is still pending.
*/
assert(handle->flags & UV_CLOSING);
assert(!(handle->flags & UV_CLOSED));
handle->flags |= UV_CLOSED;
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->flags |= UV_HANDLE_CLOSED;
switch (handle->type) {
case UV_PREPARE:
......@@ -927,6 +929,11 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
}
int uv__fd_exists(uv_loop_t* loop, int fd) {
return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL;
}
int uv_getrusage(uv_rusage_t* rusage) {
struct rusage usage;
......
......@@ -865,9 +865,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
/* If an error occurred that the sendfile fallback also won't handle, or
this is a force clone then exit. Otherwise, fall through to try using
sendfile(). */
if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
err = -errno;
if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
err = UV__ERR(errno);
goto out;
} else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
err = UV_ENOTSUP;
goto out;
}
} else {
......@@ -927,7 +929,11 @@ out:
}
}
return result;
if (result == 0)
return 0;
errno = UV__ERR(result);
return -1;
#endif
}
......@@ -1114,6 +1120,7 @@ static void uv__fs_work(struct uv__work* w) {
X(COPYFILE, uv__fs_copyfile(req));
X(FCHMOD, fchmod(req->file, req->mode));
X(FCHOWN, fchown(req->file, req->uid, req->gid));
X(LCHOWN, lchown(req->path, req->uid, req->gid));
X(FDATASYNC, uv__fs_fdatasync(req));
X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
X(FSYNC, uv__fs_fsync(req));
......@@ -1240,6 +1247,20 @@ int uv_fs_fchown(uv_loop_t* loop,
}
int uv_fs_lchown(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
uv_uid_t uid,
uv_gid_t gid,
uv_fs_cb cb) {
INIT(LCHOWN);
PATH;
req->uid = uid;
req->gid = gid;
POST;
}
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
INIT(FDATASYNC);
req->file = file;
......
......@@ -836,7 +836,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
handle->cf_cb->data = handle;
uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb);
handle->cf_cb->flags |= UV__HANDLE_INTERNAL;
handle->cf_cb->flags |= UV_HANDLE_INTERNAL;
uv_unref((uv_handle_t*) handle->cf_cb);
err = uv_mutex_init(&handle->cf_mutex);
......
......@@ -127,26 +127,6 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
/* handle flags */
enum {
UV_CLOSING = 0x01, /* uv_close() called but not finished. */
UV_CLOSED = 0x02, /* close(2) finished. */
UV_STREAM_READING = 0x04, /* uv_read_start() called. */
UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */
UV_STREAM_SHUT = 0x10, /* Write side closed. */
UV_STREAM_READABLE = 0x20, /* The stream is readable */
UV_STREAM_WRITABLE = 0x40, /* The stream is writable */
UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */
UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */
UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */
UV_TCP_NODELAY = 0x400, /* Disable Nagle. */
UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */
UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */
UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */
UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */
UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */
};
/* loop flags */
enum {
UV_LOOP_BLOCK_SIGPROF = 1
......@@ -185,6 +165,18 @@ struct uv__stream_queued_fds_s {
#define uv__nonblock uv__nonblock_fcntl
#endif
/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
* when O_NDELAY is not equal to O_NONBLOCK. Case in point: linux/sparc32
* and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit.
*
* Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it
* commutes with uv__nonblock().
*/
#if defined(__linux__) && O_NDELAY != O_NONBLOCK
#undef uv__nonblock
#define uv__nonblock uv__nonblock_fcntl
#endif
/* core */
int uv__cloexec_ioctl(int fd, int set);
int uv__cloexec_fcntl(int fd, int set);
......@@ -207,6 +199,7 @@ int uv__io_active(const uv__io_t* w, unsigned int events);
int uv__io_check_fd(uv_loop_t* loop, int fd);
void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
int uv__io_fork(uv_loop_t* loop);
int uv__fd_exists(uv_loop_t* loop, int fd);
/* async */
void uv__async_stop(uv_loop_t* loop);
......@@ -239,10 +232,6 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay);
/* pipe */
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
/* timer */
void uv__run_timers(uv_loop_t* loop);
int uv__next_timeout(const uv_loop_t* loop);
/* signal */
void uv__signal_close(uv_signal_t* handle);
void uv__signal_global_once_init(void);
......@@ -267,7 +256,6 @@ void uv__prepare_close(uv_prepare_t* handle);
void uv__process_close(uv_process_t* handle);
void uv__stream_close(uv_stream_t* handle);
void uv__tcp_close(uv_tcp_t* handle);
void uv__timer_close(uv_timer_t* handle);
void uv__udp_close(uv_udp_t* handle);
void uv__udp_finish_close(uv_udp_t* handle);
uv_handle_type uv__handle_type(int fd);
......
......@@ -261,8 +261,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w = loop->watchers[fd];
if (w == NULL) {
/* File descriptor that we've stopped watching, disarm it. */
/* TODO batch up */
/* File descriptor that we've stopped watching, disarm it.
* TODO: batch up. */
struct kevent events[1];
EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
......
......@@ -51,7 +51,7 @@
#ifdef HAVE_IFADDRS_H
# if defined(__ANDROID__)
# include "android-ifaddrs.h"
# include "uv/android-ifaddrs.h"
# else
# include <ifaddrs.h>
# endif
......@@ -388,7 +388,8 @@ 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 | UV__POLLPRI);
pe->events |=
w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
if (pe->events != 0) {
/* Run signal watchers last. This also affects child process watchers
......
......@@ -19,7 +19,7 @@
*/
#include "uv.h"
#include "tree.h"
#include "uv/tree.h"
#include "internal.h"
#include <stdint.h>
......
......@@ -20,7 +20,7 @@
*/
#include "uv.h"
#include "tree.h"
#include "uv/tree.h"
#include "internal.h"
#include "heap-inl.h"
#include <stdlib.h>
......@@ -74,7 +74,7 @@ int uv_loop_init(uv_loop_t* loop) {
goto fail_signal_init;
uv__handle_unref(&loop->child_watcher);
loop->child_watcher.flags |= UV__HANDLE_INTERNAL;
loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
QUEUE_INIT(&loop->process_handles);
err = uv_rwlock_init(&loop->cloexec_lock);
......@@ -90,7 +90,7 @@ int uv_loop_init(uv_loop_t* loop) {
goto fail_async_init;
uv__handle_unref(&loop->wq_async);
loop->wq_async.flags |= UV__HANDLE_INTERNAL;
loop->wq_async.flags |= UV_HANDLE_INTERNAL;
return 0;
......
......@@ -141,7 +141,7 @@ static void init_message_queue(uv__os390_epoll* lst) {
} msg;
/* initialize message queue */
lst->msg_queue = msgget(IPC_PRIVATE, 0622 | IPC_CREAT);
lst->msg_queue = msgget(IPC_PRIVATE, 0600 | IPC_CREAT);
if (lst->msg_queue == -1)
abort();
......@@ -215,6 +215,7 @@ uv__os390_epoll* epoll_create1(int flags) {
maybe_resize(lst, 1);
lst->items[lst->size - 1].fd = lst->msg_queue;
lst->items[lst->size - 1].events = POLLIN;
lst->items[lst->size - 1].revents = 0;
uv_once(&once, epoll_init);
uv_mutex_lock(&global_epoll_lock);
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
......@@ -252,13 +253,15 @@ int epoll_ctl(uv__os390_epoll* lst,
}
lst->items[fd].fd = fd;
lst->items[fd].events = event->events;
lst->items[fd].revents = 0;
} else if (op == EPOLL_CTL_MOD) {
if (fd >= lst->size || lst->items[fd].fd == -1) {
if (fd >= lst->size - 1 || lst->items[fd].fd == -1) {
uv_mutex_unlock(&global_epoll_lock);
errno = ENOENT;
return -1;
}
lst->items[fd].events = event->events;
lst->items[fd].revents = 0;
} else
abort();
......@@ -273,8 +276,9 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
struct pollfd* pfds;
int pollret;
int reventcount;
int nevents;
size = _SET_FDS_MSGS(size, 1, lst->size - 1);
_SET_FDS_MSGS(size, 1, lst->size - 1);
pfds = lst->items;
pollret = poll(pfds, size, timeout);
if (pollret <= 0)
......@@ -283,19 +287,28 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
pollret = _NFDS(pollret) + _NMSGS(pollret);
reventcount = 0;
nevents = 0;
for (int i = 0;
i < lst->size && i < maxevents && reventcount < pollret; ++i) {
struct epoll_event ev;
struct pollfd* pfd;
if (pfds[i].fd == -1 || pfds[i].revents == 0)
pfd = &pfds[i];
if (pfd->fd == -1 || pfd->revents == 0)
continue;
ev.fd = pfds[i].fd;
ev.events = pfds[i].revents;
events[reventcount++] = ev;
ev.fd = pfd->fd;
ev.events = pfd->revents;
if (pfd->revents & POLLIN && pfd->revents & POLLOUT)
reventcount += 2;
else if (pfd->revents & (POLLIN | POLLOUT))
++reventcount;
pfd->revents = 0;
events[nevents++] = ev;
}
return reventcount;
return nevents;
}
......@@ -491,7 +504,7 @@ ssize_t os390_readlink(const char* path, char* buf, size_t len) {
size_t strnlen(const char* str, size_t maxlen) {
void* p = memchr(str, 0, maxlen);
char* p = memchr(str, 0, maxlen);
if (p == NULL)
return maxlen;
else
......
......@@ -134,6 +134,9 @@ void uv__pipe_close(uv_pipe_t* handle) {
int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
int err;
if (uv__fd_exists(handle->loop, fd))
return UV_EEXIST;
err = uv__nonblock(fd, 1);
if (err)
return err;
......@@ -146,7 +149,7 @@ int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
return uv__stream_open((uv_stream_t*)handle,
fd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
}
......@@ -196,7 +199,7 @@ void uv_pipe_connect(uv_connect_t* req,
if (new_sock) {
err = uv__stream_open((uv_stream_t*)handle,
uv__stream_fd(handle),
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
}
if (err == 0)
......
......@@ -68,6 +68,9 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
int err;
if (uv__fd_exists(loop, fd))
return UV_EEXIST;
err = uv__io_check_fd(loop, fd);
if (err)
return err;
......
......@@ -239,9 +239,9 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
flags = 0;
if (container->flags & UV_WRITABLE_PIPE)
flags |= UV_STREAM_READABLE;
flags |= UV_HANDLE_READABLE;
if (container->flags & UV_READABLE_PIPE)
flags |= UV_STREAM_WRITABLE;
flags |= UV_HANDLE_WRITABLE;
return uv__stream_open(container->data.stream, pipefds[0], flags);
}
......
......@@ -54,8 +54,7 @@ static void uv__signal_unregister_handler(int signum);
static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
static struct uv__signal_tree_s uv__signal_tree =
RB_INITIALIZER(uv__signal_tree);
static int uv__signal_lock_pipefd[2];
static int uv__signal_lock_pipefd[2] = { -1, -1 };
RB_GENERATE_STATIC(uv__signal_tree_s,
uv_signal_s, tree_entry,
......@@ -64,7 +63,7 @@ RB_GENERATE_STATIC(uv__signal_tree_s,
static void uv__signal_global_reinit(void);
static void uv__signal_global_init(void) {
if (!uv__signal_lock_pipefd[0])
if (uv__signal_lock_pipefd[0] == -1)
/* pthread_atfork can register before and after handlers, one
* for each child. This only registers one for the child. That
* state is both persistent and cumulative, so if we keep doing
......@@ -74,15 +73,11 @@ static void uv__signal_global_init(void) {
if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
abort();
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
abort();
if (uv__signal_unlock())
abort();
uv__signal_global_reinit();
}
static void uv__signal_global_reinit(void) {
UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
/* We can only use signal-safe functions here.
* That includes read/write and close, fortunately.
* We do all of this directly here instead of resetting
......@@ -90,11 +85,26 @@ static void uv__signal_global_reinit(void) {
* uv__signal_global_once_init is only called from uv_loop_init
* and this needs to function in existing loops.
*/
uv__close(uv__signal_lock_pipefd[0]);
uv__signal_lock_pipefd[0] = -1;
uv__close(uv__signal_lock_pipefd[1]);
uv__signal_lock_pipefd[1] = -1;
uv__signal_global_init();
if (uv__signal_lock_pipefd[0] != -1) {
uv__close(uv__signal_lock_pipefd[0]);
uv__signal_lock_pipefd[0] = -1;
}
if (uv__signal_lock_pipefd[1] != -1) {
uv__close(uv__signal_lock_pipefd[1]);
uv__signal_lock_pipefd[1] = -1;
}
}
static void uv__signal_global_reinit(void) {
uv__signal_global_fini();
if (uv__make_pipe(uv__signal_lock_pipefd, 0))
abort();
if (uv__signal_unlock())
abort();
}
......@@ -103,7 +113,6 @@ void uv__signal_global_once_init(void) {
}
static int uv__signal_lock(void) {
int r;
char data;
......@@ -387,7 +396,7 @@ static int uv__signal_start(uv_signal_t* handle,
*/
first_handle = uv__signal_first_handle(signum);
if (first_handle == NULL ||
(!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) {
(!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) {
err = uv__signal_register_handler(signum, oneshot);
if (err) {
/* Registering the signal handler failed. Must be an invalid signal. */
......@@ -398,7 +407,7 @@ static int uv__signal_start(uv_signal_t* handle,
handle->signum = signum;
if (oneshot)
handle->flags |= UV__SIGNAL_ONE_SHOT;
handle->flags |= UV_SIGNAL_ONE_SHOT;
RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
......@@ -455,20 +464,20 @@ static void uv__signal_event(uv_loop_t* loop,
handle = msg->handle;
if (msg->signum == handle->signum) {
assert(!(handle->flags & UV_CLOSING));
assert(!(handle->flags & UV_HANDLE_CLOSING));
handle->signal_cb(handle, handle->signum);
}
handle->dispatched_signals++;
if (handle->flags & UV__SIGNAL_ONE_SHOT)
if (handle->flags & UV_SIGNAL_ONE_SHOT)
uv__signal_stop(handle);
/* If uv_close was called while there were caught signals that were not
* yet dispatched, the uv__finish_close was deferred. Make close pending
* now if this has happened.
*/
if ((handle->flags & UV_CLOSING) &&
if ((handle->flags & UV_HANDLE_CLOSING) &&
(handle->caught_signals == handle->dispatched_signals)) {
uv__make_close_pending((uv_handle_t*) handle);
}
......@@ -496,11 +505,11 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
if (w1->signum < w2->signum) return -1;
if (w1->signum > w2->signum) return 1;
/* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first
/* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first
* handler returned is a one-shot handler, the rest will be too.
*/
f1 = w1->flags & UV__SIGNAL_ONE_SHOT;
f2 = w2->flags & UV__SIGNAL_ONE_SHOT;
f1 = w1->flags & UV_SIGNAL_ONE_SHOT;
f2 = w2->flags & UV_SIGNAL_ONE_SHOT;
if (f1 < f2) return -1;
if (f1 > f2) return 1;
......@@ -549,8 +558,8 @@ static void uv__signal_stop(uv_signal_t* handle) {
if (first_handle == NULL) {
uv__signal_unregister_handler(handle->signum);
} else {
rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT;
first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT;
rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT;
first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT;
if (first_oneshot && !rem_oneshot) {
ret = uv__signal_register_handler(handle->signum, 1);
assert(ret == 0);
......
This diff is collapsed.
......@@ -216,7 +216,7 @@ int uv__tcp_connect(uv_connect_t* req,
err = maybe_new_socket(handle,
addr->sa_family,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
if (err)
return err;
......@@ -263,13 +263,16 @@ int uv__tcp_connect(uv_connect_t* req,
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
int err;
if (uv__fd_exists(handle->loop, sock))
return UV_EEXIST;
err = uv__nonblock(sock, 1);
if (err)
return err;
return uv__stream_open((uv_stream_t*)handle,
sock,
UV_STREAM_READABLE | UV_STREAM_WRITABLE);
UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
}
......@@ -331,7 +334,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
}
if (single_accept)
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
flags = 0;
#if defined(__MVS__)
......@@ -398,9 +401,9 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
}
if (on)
handle->flags |= UV_TCP_NODELAY;
handle->flags |= UV_HANDLE_TCP_NODELAY;
else
handle->flags &= ~UV_TCP_NODELAY;
handle->flags &= ~UV_HANDLE_TCP_NODELAY;
return 0;
}
......@@ -416,9 +419,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
}
if (on)
handle->flags |= UV_TCP_KEEPALIVE;
handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
else
handle->flags &= ~UV_TCP_KEEPALIVE;
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
/* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
* uv_tcp_t with an int that's almost never used...
......@@ -430,9 +433,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
if (enable)
handle->flags &= ~UV_TCP_SINGLE_ACCEPT;
handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
else
handle->flags |= UV_TCP_SINGLE_ACCEPT;
handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
return 0;
}
......
......@@ -423,87 +423,6 @@ int uv_sem_trywait(uv_sem_t* sem) {
return UV_EINVAL; /* Satisfy the compiler. */
}
#elif defined(__MVS__)
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
uv_sem_t semid;
int err;
union {
int val;
struct semid_ds* buf;
unsigned short* array;
} arg;
semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
if (semid == -1)
return UV__ERR(errno);
arg.val = value;
if (-1 == semctl(semid, 0, SETVAL, arg)) {
err = errno;
if (-1 == semctl(*sem, 0, IPC_RMID))
abort();
return UV__ERR(err);
}
*sem = semid;
return 0;
}
void uv_sem_destroy(uv_sem_t* sem) {
if (-1 == semctl(*sem, 0, IPC_RMID))
abort();
}
void uv_sem_post(uv_sem_t* sem) {
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = 1;
buf.sem_flg = 0;
if (-1 == semop(*sem, &buf, 1))
abort();
}
void uv_sem_wait(uv_sem_t* sem) {
struct sembuf buf;
int op_status;
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = 0;
do
op_status = semop(*sem, &buf, 1);
while (op_status == -1 && errno == EINTR);
if (op_status)
abort();
}
int uv_sem_trywait(uv_sem_t* sem) {
struct sembuf buf;
int op_status;
buf.sem_num = 0;
buf.sem_op = -1;
buf.sem_flg = IPC_NOWAIT;
do
op_status = semop(*sem, &buf, 1);
while (op_status == -1 && errno == EINTR);
if (op_status) {
if (errno == EAGAIN)
return UV_EAGAIN;
abort();
}
return 0;
}
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
#ifdef __GLIBC__
......@@ -517,18 +436,22 @@ int uv_sem_trywait(uv_sem_t* sem) {
* a pointer to the actual struct we're using underneath. */
static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
static int glibc_needs_custom_semaphore = 0;
static int platform_needs_custom_semaphore = 0;
static void glibc_version_check(void) {
const char* version = gnu_get_libc_version();
glibc_needs_custom_semaphore =
platform_needs_custom_semaphore =
version[0] == '2' && version[1] == '.' &&
atoi(version + 2) < 21;
}
#else /* !defined(__GLIBC__) */
#elif defined(__MVS__)
#define platform_needs_custom_semaphore 1
#define glibc_needs_custom_semaphore 0
#else /* !defined(__GLIBC__) && !defined(__MVS__) */
#define platform_needs_custom_semaphore 0
#endif
......@@ -538,8 +461,9 @@ typedef struct uv_semaphore_s {
unsigned int value;
} uv_semaphore_t;
#if defined(__GLIBC__) || platform_needs_custom_semaphore
STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
#endif
static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
int err;
......@@ -670,7 +594,7 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) {
uv_once(&glibc_version_check_once, glibc_version_check);
#endif
if (glibc_needs_custom_semaphore)
if (platform_needs_custom_semaphore)
return uv__custom_sem_init(sem, value);
else
return uv__sem_init(sem, value);
......@@ -678,7 +602,7 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) {
void uv_sem_destroy(uv_sem_t* sem) {
if (glibc_needs_custom_semaphore)
if (platform_needs_custom_semaphore)
uv__custom_sem_destroy(sem);
else
uv__sem_destroy(sem);
......@@ -686,7 +610,7 @@ void uv_sem_destroy(uv_sem_t* sem) {
void uv_sem_post(uv_sem_t* sem) {
if (glibc_needs_custom_semaphore)
if (platform_needs_custom_semaphore)
uv__custom_sem_post(sem);
else
uv__sem_post(sem);
......@@ -694,7 +618,7 @@ void uv_sem_post(uv_sem_t* sem) {
void uv_sem_wait(uv_sem_t* sem) {
if (glibc_needs_custom_semaphore)
if (platform_needs_custom_semaphore)
uv__custom_sem_wait(sem);
else
uv__sem_wait(sem);
......@@ -702,7 +626,7 @@ void uv_sem_wait(uv_sem_t* sem) {
int uv_sem_trywait(uv_sem_t* sem) {
if (glibc_needs_custom_semaphore)
if (platform_needs_custom_semaphore)
return uv__custom_sem_trywait(sem);
else
return uv__sem_trywait(sem);
......
......@@ -135,7 +135,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
if (r < 0) {
/* fallback to using blocking writes */
if (!readable)
flags |= UV_STREAM_BLOCKING;
flags |= UV_HANDLE_BLOCKING_WRITES;
goto skip;
}
......@@ -177,7 +177,7 @@ skip:
* the handle queue, since it was added by uv__handle_init in uv_stream_init.
*/
if (!(flags & UV_STREAM_BLOCKING))
if (!(flags & UV_HANDLE_BLOCKING_WRITES))
uv__nonblock(fd, 1);
#if defined(__APPLE__)
......@@ -195,9 +195,9 @@ skip:
#endif
if (readable)
flags |= UV_STREAM_READABLE;
flags |= UV_HANDLE_READABLE;
else
flags |= UV_STREAM_WRITABLE;
flags |= UV_HANDLE_WRITABLE;
uv__stream_open((uv_stream_t*) tty, fd, flags);
tty->mode = UV_TTY_MODE_NORMAL;
......
......@@ -92,8 +92,8 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
uv_udp_send_t* req;
QUEUE* q;
assert(!(handle->flags & UV_UDP_PROCESSING));
handle->flags |= UV_UDP_PROCESSING;
assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING));
handle->flags |= UV_HANDLE_UDP_PROCESSING;
while (!QUEUE_EMPTY(&handle->write_completed_queue)) {
q = QUEUE_HEAD(&handle->write_completed_queue);
......@@ -128,7 +128,7 @@ static void uv__udp_run_completed(uv_udp_t* handle) {
uv__handle_stop(handle);
}
handle->flags &= ~UV_UDP_PROCESSING;
handle->flags &= ~UV_HANDLE_UDP_PROCESSING;
}
......@@ -427,7 +427,7 @@ int uv__udp_send(uv_udp_send_t* req,
QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
uv__handle_start(handle);
if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) {
if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) {
uv__udp_sendmsg(handle);
/* `uv__udp_sendmsg` may not be able to do non-blocking write straight
......@@ -624,6 +624,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
if (handle->io_watcher.fd != -1)
return UV_EBUSY;
if (uv__fd_exists(handle->loop, sock))
return UV_EEXIST;
err = uv__nonblock(sock, 1);
if (err)
return err;
......
......@@ -155,6 +155,18 @@ static const char* uv__unknown_err_code(int err) {
return copy != NULL ? copy : "Unknown system error";
}
#define UV_ERR_NAME_GEN_R(name, _) \
case UV_## name: \
snprintf(buf, buflen, "%s", #name); break;
char* uv_err_name_r(int err, char* buf, size_t buflen) {
switch (err) {
UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
default: snprintf(buf, buflen, "Unknown system error %d", err);
}
return buf;
}
#undef UV_ERR_NAME_GEN_R
#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
const char* uv_err_name(int err) {
......@@ -166,6 +178,19 @@ const char* uv_err_name(int err) {
#undef UV_ERR_NAME_GEN
#define UV_STRERROR_GEN_R(name, msg) \
case UV_ ## name: \
snprintf(buf, buflen, "%s", msg); break;
char* uv_strerror_r(int err, char* buf, size_t buflen) {
switch (err) {
UV_ERRNO_MAP(UV_STRERROR_GEN_R)
default: snprintf(buf, buflen, "Unknown system error %d", err);
}
return buf;
}
#undef UV_STRERROR_GEN_R
#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
const char* uv_strerror(int err) {
switch (err) {
......@@ -357,7 +382,7 @@ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->handle_queue, q);
if (h->flags & UV__HANDLE_INTERNAL) continue;
if (h->flags & UV_HANDLE_INTERNAL) continue;
walk_cb(h, arg);
}
}
......@@ -386,9 +411,9 @@ static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
fprintf(stream,
"[%c%c%c] %-8s %p\n",
"R-"[!(h->flags & UV__HANDLE_REF)],
"A-"[!(h->flags & UV__HANDLE_ACTIVE)],
"I-"[!(h->flags & UV__HANDLE_INTERNAL)],
"R-"[!(h->flags & UV_HANDLE_REF)],
"A-"[!(h->flags & UV_HANDLE_ACTIVE)],
"I-"[!(h->flags & UV_HANDLE_INTERNAL)],
type,
(void*)h);
}
......@@ -632,7 +657,7 @@ int uv_loop_close(uv_loop_t* loop) {
QUEUE_FOREACH(q, &loop->handle_queue) {
h = QUEUE_DATA(q, uv_handle_t, handle_queue);
if (!(h->flags & UV__HANDLE_INTERNAL))
if (!(h->flags & UV_HANDLE_INTERNAL))
return UV_EBUSY;
}
......
......@@ -32,13 +32,13 @@
#include <stddef.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
# include "stdint-msvc2008.h"
# include "uv/stdint-msvc2008.h"
#else
# include <stdint.h>
#endif
#include "uv.h"
#include "tree.h"
#include "uv/tree.h"
#include "queue.h"
#if EDOM > 0
......@@ -59,22 +59,67 @@ extern int snprintf(char*, size_t, const char*, ...);
#define STATIC_ASSERT(expr) \
void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
#ifndef _WIN32
/* Handle flags. Some flags are specific to Windows or UNIX. */
enum {
UV__SIGNAL_ONE_SHOT = 0x80000, /* On signal reception remove sighandler */
UV__HANDLE_INTERNAL = 0x8000,
UV__HANDLE_ACTIVE = 0x4000,
UV__HANDLE_REF = 0x2000,
UV__HANDLE_CLOSING = 0 /* no-op on unix */
/* Used by all handles. */
UV_HANDLE_CLOSING = 0x00000001,
UV_HANDLE_CLOSED = 0x00000002,
UV_HANDLE_ACTIVE = 0x00000004,
UV_HANDLE_REF = 0x00000008,
UV_HANDLE_INTERNAL = 0x00000010,
UV_HANDLE_ENDGAME_QUEUED = 0x00000020,
/* Used by streams. */
UV_HANDLE_LISTENING = 0x00000040,
UV_HANDLE_CONNECTION = 0x00000080,
UV_HANDLE_SHUTTING = 0x00000100,
UV_HANDLE_SHUT = 0x00000200,
UV_HANDLE_READ_PARTIAL = 0x00000400,
UV_HANDLE_READ_EOF = 0x00000800,
/* Used by streams and UDP handles. */
UV_HANDLE_READING = 0x00001000,
UV_HANDLE_BOUND = 0x00002000,
UV_HANDLE_READABLE = 0x00004000,
UV_HANDLE_WRITABLE = 0x00008000,
UV_HANDLE_READ_PENDING = 0x00010000,
UV_HANDLE_SYNC_BYPASS_IOCP = 0x00020000,
UV_HANDLE_ZERO_READ = 0x00040000,
UV_HANDLE_EMULATE_IOCP = 0x00080000,
UV_HANDLE_BLOCKING_WRITES = 0x00100000,
UV_HANDLE_CANCELLATION_PENDING = 0x00200000,
/* Used by uv_tcp_t and uv_udp_t handles */
UV_HANDLE_IPV6 = 0x00400000,
/* Only used by uv_tcp_t handles. */
UV_HANDLE_TCP_NODELAY = 0x01000000,
UV_HANDLE_TCP_KEEPALIVE = 0x02000000,
UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000,
UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000,
UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000,
UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000,
/* Only used by uv_udp_t handles. */
UV_HANDLE_UDP_PROCESSING = 0x01000000,
/* Only used by uv_pipe_t handles. */
UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000,
UV_HANDLE_PIPESERVER = 0x02000000,
/* Only used by uv_tty_t handles. */
UV_HANDLE_TTY_READABLE = 0x01000000,
UV_HANDLE_TTY_RAW = 0x02000000,
UV_HANDLE_TTY_SAVED_POSITION = 0x04000000,
UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000,
/* Only used by uv_signal_t handles. */
UV_SIGNAL_ONE_SHOT_DISPATCHED = 0x01000000,
UV_SIGNAL_ONE_SHOT = 0x02000000,
/* Only used by uv_poll_t handles. */
UV_HANDLE_POLL_SLOW = 0x01000000
};
#else
# define UV__SIGNAL_ONE_SHOT_DISPATCHED 0x200
# define UV__SIGNAL_ONE_SHOT 0x100
# define UV__HANDLE_INTERNAL 0x80
# define UV__HANDLE_ACTIVE 0x40
# define UV__HANDLE_REF 0x20
# define UV__HANDLE_CLOSING 0x01
#endif
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
......@@ -132,6 +177,10 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
void uv__fs_scandir_cleanup(uv_fs_t* req);
int uv__next_timeout(const uv_loop_t* loop);
void uv__run_timers(uv_loop_t* loop);
void uv__timer_close(uv_timer_t* handle);
#define uv__has_active_reqs(loop) \
((loop)->active_reqs.count > 0)
......@@ -164,49 +213,47 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
while (0)
#define uv__is_active(h) \
(((h)->flags & UV__HANDLE_ACTIVE) != 0)
(((h)->flags & UV_HANDLE_ACTIVE) != 0)
#define uv__is_closing(h) \
(((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0)
(((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0)
#define uv__handle_start(h) \
do { \
assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \
if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break; \
(h)->flags |= UV__HANDLE_ACTIVE; \
if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h); \
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \
(h)->flags |= UV_HANDLE_ACTIVE; \
if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \
} \
while (0)
#define uv__handle_stop(h) \
do { \
assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \
if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break; \
(h)->flags &= ~UV__HANDLE_ACTIVE; \
if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h); \
if (((h)->flags & UV_HANDLE_ACTIVE) == 0) break; \
(h)->flags &= ~UV_HANDLE_ACTIVE; \
if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_rm(h); \
} \
while (0)
#define uv__handle_ref(h) \
do { \
if (((h)->flags & UV__HANDLE_REF) != 0) break; \
(h)->flags |= UV__HANDLE_REF; \
if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \
if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \
if (((h)->flags & UV_HANDLE_REF) != 0) break; \
(h)->flags |= UV_HANDLE_REF; \
if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \
} \
while (0)
#define uv__handle_unref(h) \
do { \
if (((h)->flags & UV__HANDLE_REF) == 0) break; \
(h)->flags &= ~UV__HANDLE_REF; \
if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \
if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \
if (((h)->flags & UV_HANDLE_REF) == 0) break; \
(h)->flags &= ~UV_HANDLE_REF; \
if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \
} \
while (0)
#define uv__has_ref(h) \
(((h)->flags & UV__HANDLE_REF) != 0)
(((h)->flags & UV_HANDLE_REF) != 0)
#if defined(_WIN32)
# define uv__handle_platform_init(h) ((h)->u.fd = -1)
......@@ -218,7 +265,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req);
do { \
(h)->loop = (loop_); \
(h)->type = (type_); \
(h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \
(h)->flags = UV_HANDLE_REF; /* Ref the loop when active. */ \
QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \
uv__handle_platform_init(h); \
} \
......
......@@ -29,7 +29,7 @@
void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
if (handle->flags & UV__HANDLE_CLOSING &&
if (handle->flags & UV_HANDLE_CLOSING &&
!handle->async_sent) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
uv__handle_close(handle);
......@@ -71,9 +71,9 @@ int uv_async_send(uv_async_t* handle) {
return -1;
}
/* The user should make sure never to call uv_async_send to a closing */
/* or closed handle. */
assert(!(handle->flags & UV__HANDLE_CLOSING));
/* The user should make sure never to call uv_async_send to a closing or
* closed handle. */
assert(!(handle->flags & UV_HANDLE_CLOSING));
if (!uv__atomic_exchange_set(&handle->async_sent)) {
POST_COMPLETION_FOR_REQ(loop, &handle->async_req);
......@@ -90,7 +90,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
handle->async_sent = 0;
if (handle->flags & UV__HANDLE_CLOSING) {
if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*)handle);
} else if (handle->async_cb != NULL) {
handle->async_cb(handle);
......
......@@ -29,10 +29,10 @@
/* Atomic set operation on char */
#ifdef _MSC_VER /* MSVC */
/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */
/* efficient than InterlockedExchange, but InterlockedExchange8 does not */
/* exist, and interlocked operations on larger targets might require the */
/* target to be aligned. */
/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less
* efficient than InterlockedExchange, but InterlockedExchange8 does not exist,
* and interlocked operations on larger targets might require the target to be
* aligned. */
#pragma intrinsic(_InterlockedOr8)
static char INLINE uv__atomic_exchange_set(char volatile* target) {
......
......@@ -33,6 +33,7 @@
#include "internal.h"
#include "queue.h"
#include "handle-inl.h"
#include "heap-inl.h"
#include "req-inl.h"
/* uv_once initialization guards */
......@@ -221,6 +222,7 @@ static void uv_init(void) {
int uv_loop_init(uv_loop_t* loop) {
struct heap* timer_heap;
int err;
/* Initialize libuv itself first */
......@@ -246,7 +248,11 @@ int uv_loop_init(uv_loop_t* loop) {
loop->endgame_handles = NULL;
RB_INIT(&loop->timers);
loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap));
if (timer_heap == NULL)
goto fail_timers_alloc;
heap_init(timer_heap);
loop->check_handles = NULL;
loop->prepare_handles = NULL;
......@@ -273,7 +279,7 @@ int uv_loop_init(uv_loop_t* loop) {
goto fail_async_init;
uv__handle_unref(&loop->wq_async);
loop->wq_async.flags |= UV__HANDLE_INTERNAL;
loop->wq_async.flags |= UV_HANDLE_INTERNAL;
err = uv__loops_add(loop);
if (err)
......@@ -285,6 +291,10 @@ fail_async_init:
uv_mutex_destroy(&loop->wq_mutex);
fail_mutex_init:
uv__free(timer_heap);
loop->timer_heap = NULL;
fail_timers_alloc:
CloseHandle(loop->iocp);
loop->iocp = INVALID_HANDLE_VALUE;
......@@ -292,6 +302,13 @@ fail_mutex_init:
}
void uv_update_time(uv_loop_t* loop) {
uint64_t new_time = uv__hrtime(1000);
assert(new_time >= loop->time);
loop->time = new_time;
}
void uv__once_init(void) {
uv_once(&uv_init_guard_, uv_init);
}
......@@ -320,6 +337,9 @@ void uv__loop_close(uv_loop_t* loop) {
uv_mutex_unlock(&loop->wq_mutex);
uv_mutex_destroy(&loop->wq_mutex);
uv__free(loop->timer_heap);
loop->timer_heap = NULL;
CloseHandle(loop->iocp);
}
......@@ -359,58 +379,7 @@ int uv_backend_timeout(const uv_loop_t* loop) {
}
static void uv_poll(uv_loop_t* loop, DWORD timeout) {
DWORD bytes;
ULONG_PTR key;
OVERLAPPED* overlapped;
uv_req_t* req;
int repeat;
uint64_t timeout_time;
timeout_time = loop->time + timeout;
for (repeat = 0; ; repeat++) {
GetQueuedCompletionStatus(loop->iocp,
&bytes,
&key,
&overlapped,
timeout);
if (overlapped) {
/* Package was dequeued */
req = uv_overlapped_to_req(overlapped);
uv_insert_pending_req(loop, req);
/* Some time might have passed waiting for I/O,
* so update the loop time here.
*/
uv_update_time(loop);
} else if (GetLastError() != WAIT_TIMEOUT) {
/* Serious error */
uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
} else if (timeout > 0) {
/* GetQueuedCompletionStatus can occasionally return a little early.
* Make sure that the desired timeout target time is reached.
*/
uv_update_time(loop);
if (timeout_time > loop->time) {
timeout = (DWORD)(timeout_time - loop->time);
/* The first call to GetQueuedCompletionStatus should return very
* close to the target time and the second should reach it, but
* this is not stated in the documentation. To make sure a busy
* loop cannot happen, the timeout is increased exponentially
* starting on the third round.
*/
timeout += repeat ? (1 << (repeat - 1)) : 0;
continue;
}
}
break;
}
}
static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
static void uv__poll(uv_loop_t* loop, DWORD timeout) {
BOOL success;
uv_req_t* req;
OVERLAPPED_ENTRY overlappeds[128];
......@@ -422,12 +391,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
timeout_time = loop->time + timeout;
for (repeat = 0; ; repeat++) {
success = pGetQueuedCompletionStatusEx(loop->iocp,
overlappeds,
ARRAY_SIZE(overlappeds),
&count,
timeout,
FALSE);
success = GetQueuedCompletionStatusEx(loop->iocp,
overlappeds,
ARRAY_SIZE(overlappeds),
&count,
timeout,
FALSE);
if (success) {
for (i = 0; i < count; i++) {
......@@ -485,12 +454,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;
int ran_pending;
void (*poll)(uv_loop_t* loop, DWORD timeout);
if (pGetQueuedCompletionStatusEx)
poll = &uv_poll_ex;
else
poll = &uv_poll;
r = uv__loop_alive(loop);
if (!r)
......@@ -498,7 +461,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
while (r != 0 && loop->stop_flag == 0) {
uv_update_time(loop);
uv_process_timers(loop);
uv__run_timers(loop);
ran_pending = uv_process_reqs(loop);
uv_idle_invoke(loop);
......@@ -508,7 +471,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
(*poll)(loop, timeout);
uv__poll(loop, timeout);
uv_check_invoke(loop);
uv_process_endgames(loop);
......@@ -522,7 +485,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
uv_process_timers(loop);
uv__run_timers(loop);
}
r = uv__loop_alive(loop);
......
......@@ -46,8 +46,8 @@ void uv_fatal_error(const int errorno, const char* syscall) {
errmsg = "Unknown error";
}
/* FormatMessage messages include a newline character already, */
/* so don't add another. */
/* FormatMessage messages include a newline character already, so don't add
* another. */
if (syscall) {
fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);
} else {
......
......@@ -419,7 +419,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
* - We are not active, just ignore the callback
*/
if (!uv__is_active(handle)) {
if (handle->flags & UV__HANDLE_CLOSING) {
if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
}
return;
......@@ -543,7 +543,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
}
offset = file_info->NextEntryOffset;
} while (offset && !(handle->flags & UV__HANDLE_CLOSING));
} while (offset && !(handle->flags & UV_HANDLE_CLOSING));
} else {
handle->cb(handle, NULL, UV_CHANGE, 0);
}
......@@ -552,7 +552,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
handle->cb(handle, NULL, 0, uv_translate_sys_error(err));
}
if (!(handle->flags & UV__HANDLE_CLOSING)) {
if (!(handle->flags & UV_HANDLE_CLOSING)) {
uv_fs_event_queue_readdirchanges(loop, handle);
} else {
uv_want_endgame(loop, (uv_handle_t*)handle);
......@@ -573,7 +573,7 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) {
if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
if (handle->buffer) {
......
......@@ -326,12 +326,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
/* Real symlinks can contain pretty much everything, but the only thing */
/* we really care about is undoing the implicit conversion to an NT */
/* namespaced path that CreateSymbolicLink will perform on absolute */
/* paths. If the path is win32-namespaced then the user must have */
/* explicitly made it so, and we better just return the unmodified */
/* reparse data. */
/* Real symlinks can contain pretty much everything, but the only thing we
* really care about is undoing the implicit conversion to an NT namespaced
* path that CreateSymbolicLink will perform on absolute paths. If the path
* is win32-namespaced then the user must have explicitly made it so, and
* we better just return the unmodified reparse data. */
if (w_target_len >= 4 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
......@@ -352,8 +351,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
(w_target[5] == L'N' || w_target[5] == L'n') &&
(w_target[6] == L'C' || w_target[6] == L'c') &&
w_target[7] == L'\\') {
/* \??\UNC\<server>\<share>\ - make sure the final path looks like */
/* \\<server>\<share>\ */
/* \??\UNC\<server>\<share>\ - make sure the final path looks like
* \\<server>\<share>\ */
w_target += 6;
w_target[0] = L'\\';
w_target_len -= 6;
......@@ -368,11 +367,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
/* Only treat junctions that look like \??\<drive>:\ as symlink. */
/* Junctions can also be used as mount points, like \??\Volume{<guid>}, */
/* but that's confusing for programs since they wouldn't be able to */
/* actually understand such a path when returned by uv_readlink(). */
/* UNC paths are never valid for junctions so we don't care about them. */
/* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
* can also be used as mount points, like \??\Volume{<guid>}, but that's
* confusing for programs since they wouldn't be able to actually
* understand such a path when returned by uv_readlink(). UNC paths are
* never valid for junctions so we don't care about them. */
if (!(w_target_len >= 6 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
......@@ -409,8 +408,8 @@ void fs__open(uv_fs_t* req) {
int fd, current_umask;
int flags = req->fs.info.file_flags;
/* Obtain the active umask. umask() never fails and returns the previous */
/* umask. */
/* Obtain the active umask. umask() never fails and returns the previous
* umask. */
current_umask = umask(0);
umask(current_umask);
......@@ -530,8 +529,8 @@ void fs__open(uv_fs_t* req) {
DWORD error = GetLastError();
if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
!(flags & UV_FS_O_EXCL)) {
/* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */
/* specified, it means the path referred to a directory. */
/* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
* specified, it means the path referred to a directory. */
SET_REQ_UV_ERROR(req, UV_EISDIR, error);
} else {
SET_REQ_WIN32_ERROR(req, GetLastError());
......@@ -756,9 +755,9 @@ void fs__unlink(uv_fs_t* req) {
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
/* Do not allow deletion of directories, unless it is a symlink. When */
/* the path refers to a non-symlink directory, report EPERM as mandated */
/* by POSIX.1. */
/* Do not allow deletion of directories, unless it is a symlink. When the
* path refers to a non-symlink directory, report EPERM as mandated by
* POSIX.1. */
/* Check if it is a reparse point. If it's not, it's a normal directory. */
if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
......@@ -767,8 +766,8 @@ void fs__unlink(uv_fs_t* req) {
return;
}
/* Read the reparse point and check if it is a valid symlink. */
/* If not, don't unlink. */
/* Read the reparse point and check if it is a valid symlink. If not, don't
* unlink. */
if (fs__readlink_handle(handle, NULL, NULL) < 0) {
DWORD error = GetLastError();
if (error == ERROR_SYMLINK_NOT_SUPPORTED)
......@@ -1490,6 +1489,7 @@ static void fs__chmod(uv_fs_t* req) {
static void fs__fchmod(uv_fs_t* req) {
int fd = req->file.fd;
int clear_archive_flag;
HANDLE handle;
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
......@@ -1497,7 +1497,11 @@ static void fs__fchmod(uv_fs_t* req) {
VERIFY_FD(fd, req);
handle = uv__get_osfhandle(fd);
handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
nt_status = pNtQueryInformationFile(handle,
&io_status,
......@@ -1507,7 +1511,27 @@ static void fs__fchmod(uv_fs_t* req) {
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
return;
goto fchmod_cleanup;
}
/* Test if the Archive attribute is cleared */
if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
/* Set Archive flag, otherwise setting or clearing the read-only
flag will not work */
file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
nt_status = pNtSetInformationFile(handle,
&io_status,
&file_info,
sizeof file_info,
FileBasicInformation);
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
goto fchmod_cleanup;
}
/* Remeber to clear the flag later on */
clear_archive_flag = 1;
} else {
clear_archive_flag = 0;
}
if (req->fs.info.mode & _S_IWRITE) {
......@@ -1524,10 +1548,28 @@ static void fs__fchmod(uv_fs_t* req) {
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
return;
goto fchmod_cleanup;
}
if (clear_archive_flag) {
file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
if (file_info.FileAttributes == 0) {
file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
}
nt_status = pNtSetInformationFile(handle,
&io_status,
&file_info,
sizeof file_info,
FileBasicInformation);
if (!NT_SUCCESS(nt_status)) {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
goto fchmod_cleanup;
}
}
SET_REQ_SUCCESS(req);
fchmod_cleanup:
CloseHandle(handle);
}
......@@ -1787,17 +1829,13 @@ static void fs__symlink(uv_fs_t* req) {
fs__create_junction(req, pathw, new_pathw);
return;
}
if (!pCreateSymbolicLinkW) {
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
return;
}
if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
else
flags = uv__file_symlink_usermode_flag;
if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) {
if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
SET_REQ_RESULT(req, 0);
return;
}
......@@ -1854,7 +1892,7 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
WCHAR* w_realpath_ptr = NULL;
WCHAR* w_realpath_buf;
w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
if (w_realpath_len == 0) {
return -1;
}
......@@ -1866,10 +1904,8 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
}
w_realpath_ptr = w_realpath_buf;
if (pGetFinalPathNameByHandleW(handle,
w_realpath_ptr,
w_realpath_len,
VOLUME_NAME_DOS) == 0) {
if (GetFinalPathNameByHandleW(
handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
uv__free(w_realpath_buf);
SetLastError(ERROR_INVALID_HANDLE);
return -1;
......@@ -1901,11 +1937,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
static void fs__realpath(uv_fs_t* req) {
HANDLE handle;
if (!pGetFinalPathNameByHandleW) {
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
return;
}
handle = CreateFileW(req->file.pathw,
0,
0,
......@@ -1940,6 +1971,10 @@ static void fs__fchown(uv_fs_t* req) {
}
static void fs__lchown(uv_fs_t* req) {
req->result = 0;
}
static void uv__fs_work(struct uv__work* w) {
uv_fs_t* req;
......@@ -1977,6 +2012,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(REALPATH, realpath)
XX(CHOWN, chown)
XX(FCHOWN, fchown);
XX(LCHOWN, lchown);
default:
assert(!"bad uv_fs_type");
}
......@@ -2262,6 +2298,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
}
int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
uv_gid_t gid, uv_fs_cb cb) {
int err;
INIT(UV_FS_LCHOWN);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
POST;
}
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
......
......@@ -71,8 +71,8 @@ int uv__getaddrinfo_translate_error(int sys_err) {
#endif
/* adjust size value to be multiple of 4. Use to keep pointer aligned */
/* Do we need different versions of this for different architectures? */
/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
* Do we need different versions of this for different architectures? */
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
#ifndef NDIS_IF_MAX_STRING_SIZE
......@@ -124,8 +124,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
}
if (req->retcode == 0) {
/* convert addrinfoW to addrinfo */
/* first calculate required length */
/* Convert addrinfoW to addrinfo. First calculate required length. */
addrinfow_ptr = req->addrinfow;
while (addrinfow_ptr != NULL) {
addrinfo_len += addrinfo_struct_len +
......@@ -313,8 +312,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* save alloc_ptr now so we can free if error */
req->alloc = (void*)alloc_ptr;
/* convert node string to UTF16 into allocated memory and save pointer in */
/* the request. */
/* Convert node string to UTF16 into allocated memory and save pointer in the
* request. */
if (node != NULL) {
req->node = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
......@@ -331,8 +330,8 @@ int uv_getaddrinfo(uv_loop_t* loop,
req->node = NULL;
}
/* convert service string to UTF16 into allocated memory and save pointer */
/* in the req. */
/* Convert service string to UTF16 into allocated memory and save pointer in
* the req. */
if (service != NULL) {
req->service = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
......
......@@ -32,7 +32,7 @@
#define DECREASE_ACTIVE_COUNT(loop, handle) \
do { \
if (--(handle)->activecnt == 0 && \
!((handle)->flags & UV__HANDLE_CLOSING)) { \
!((handle)->flags & UV_HANDLE_CLOSING)) { \
uv__handle_stop((handle)); \
} \
assert((handle)->activecnt >= 0); \
......@@ -53,7 +53,7 @@
assert(handle->reqs_pending > 0); \
handle->reqs_pending--; \
\
if (handle->flags & UV__HANDLE_CLOSING && \
if (handle->flags & UV_HANDLE_CLOSING && \
handle->reqs_pending == 0) { \
uv_want_endgame(loop, (uv_handle_t*)handle); \
} \
......@@ -62,14 +62,14 @@
#define uv__handle_closing(handle) \
do { \
assert(!((handle)->flags & UV__HANDLE_CLOSING)); \
assert(!((handle)->flags & UV_HANDLE_CLOSING)); \
\
if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \
((handle)->flags & UV__HANDLE_REF))) \
if (!(((handle)->flags & UV_HANDLE_ACTIVE) && \
((handle)->flags & UV_HANDLE_REF))) \
uv__active_handle_add((uv_handle_t*) (handle)); \
\
(handle)->flags |= UV__HANDLE_CLOSING; \
(handle)->flags &= ~UV__HANDLE_ACTIVE; \
(handle)->flags |= UV_HANDLE_CLOSING; \
(handle)->flags &= ~UV_HANDLE_ACTIVE; \
} while (0)
......@@ -126,7 +126,8 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
break;
case UV_TIMER:
uv_timer_endgame(loop, (uv_timer_t*) handle);
uv__timer_close((uv_timer_t*) handle);
uv__handle_close(handle);
break;
case UV_PREPARE:
......@@ -164,10 +165,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) {
INLINE static HANDLE uv__get_osfhandle(int fd)
{
/* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */
/* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */
/* for invalid FDs in release builds (or if you let the assert continue). */
/* So this wrapper function disables asserts when calling _get_osfhandle. */
/* _get_osfhandle() raises an assert in debug builds if the FD is invalid.
* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for
* invalid FDs in release builds (or if you let the assert continue). So this
* wrapper function disables asserts when calling _get_osfhandle. */
HANDLE handle;
UV_BEGIN_DISABLE_CRT_ASSERT();
......
......@@ -59,15 +59,15 @@ uv_handle_type uv_guess_handle(uv_file file) {
int uv_is_active(const uv_handle_t* handle) {
return (handle->flags & UV__HANDLE_ACTIVE) &&
!(handle->flags & UV__HANDLE_CLOSING);
return (handle->flags & UV_HANDLE_ACTIVE) &&
!(handle->flags & UV_HANDLE_CLOSING);
}
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_loop_t* loop = handle->loop;
if (handle->flags & UV__HANDLE_CLOSING) {
if (handle->flags & UV_HANDLE_CLOSING) {
assert(0);
return;
}
......@@ -150,7 +150,7 @@ 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));
return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED));
}
......
......@@ -25,7 +25,7 @@
#include "uv.h"
#include "../uv-common.h"
#include "tree.h"
#include "uv/tree.h"
#include "winapi.h"
#include "winsock.h"
......@@ -57,78 +57,15 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
#define UV_END_DISABLE_CRT_ASSERT()
#endif
/*
* Handles
* (also see handle-inl.h)
*/
/* Used by all handles. */
#define UV_HANDLE_CLOSED 0x00000002
#define UV_HANDLE_ENDGAME_QUEUED 0x00000008
/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */
/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */
/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */
/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */
/* Used by streams and UDP handles. */
#define UV_HANDLE_READING 0x00000100
#define UV_HANDLE_BOUND 0x00000200
#define UV_HANDLE_LISTENING 0x00000800
#define UV_HANDLE_CONNECTION 0x00001000
#define UV_HANDLE_READABLE 0x00008000
#define UV_HANDLE_WRITABLE 0x00010000
#define UV_HANDLE_READ_PENDING 0x00020000
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000
#define UV_HANDLE_ZERO_READ 0x00080000
#define UV_HANDLE_EMULATE_IOCP 0x00100000
#define UV_HANDLE_BLOCKING_WRITES 0x00200000
#define UV_HANDLE_CANCELLATION_PENDING 0x00400000
/* Used by uv_tcp_t and uv_udp_t handles */
#define UV_HANDLE_IPV6 0x01000000
/* Only used by uv_tcp_t handles. */
#define UV_HANDLE_TCP_NODELAY 0x02000000
#define UV_HANDLE_TCP_KEEPALIVE 0x04000000
#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000
#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000
#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000
#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000
/* Only used by uv_pipe_t handles. */
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000
#define UV_HANDLE_PIPESERVER 0x02000000
#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000
/* Only used by uv_tty_t handles. */
#define UV_HANDLE_TTY_READABLE 0x01000000
#define UV_HANDLE_TTY_RAW 0x02000000
#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000
/* Only used by uv_poll_t handles. */
#define UV_HANDLE_POLL_SLOW 0x02000000
/*
* Requests: see req-inl.h
*/
/*
* Streams: see stream-inl.h
*/
/*
* TCP
*/
typedef struct {
WSAPROTOCOL_INFOW socket_info;
int delayed_error;
} uv__ipc_socket_info_ex;
uint32_t delayed_error;
uint32_t flags; /* Either zero or UV_HANDLE_CONNECTION. */
} uv__ipc_socket_xfer_info_t;
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
......@@ -150,11 +87,10 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex,
int tcp_connection);
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
LPWSAPROTOCOL_INFOW protocol_info);
int uv__tcp_xfer_export(uv_tcp_t* handle,
int pid,
uv__ipc_socket_xfer_info_t* xfer_info);
int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info);
/*
......@@ -178,14 +114,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle,
uv_write_cb cb);
void uv__pipe_pause_read(uv_pipe_t* handle);
void uv__pipe_unpause_read(uv_pipe_t* handle);
void uv__pipe_stop_read(uv_pipe_t* handle);
void uv__pipe_read_stop(uv_pipe_t* handle);
int uv__pipe_write(uv_loop_t* loop,
uv_write_t* req,
uv_pipe_t* handle,
const uv_buf_t bufs[],
size_t nbufs,
uv_stream_t* send_handle,
uv_write_cb cb);
void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
uv_req_t* req);
......@@ -247,15 +183,6 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
/*
* Timers
*/
void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle);
DWORD uv__next_timeout(const uv_loop_t* loop);
void uv_process_timers(uv_loop_t* loop);
/*
* Loop watchers
*/
......@@ -332,7 +259,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_current_pid(void);
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
......
......@@ -27,7 +27,7 @@
void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
if (handle->flags & UV__HANDLE_CLOSING) {
if (handle->flags & UV_HANDLE_CLOSING) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
handle->flags |= UV_HANDLE_CLOSED;
uv__handle_close(handle);
......
This diff is collapsed.
......@@ -91,16 +91,16 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
handle->mask_events_1 = handle->events;
handle->mask_events_2 = 0;
} else {
/* Just wait until there's an unsubmitted req. */
/* This will happen almost immediately as one of the 2 outstanding */
/* requests is about to return. When this happens, */
/* uv__fast_poll_process_poll_req will be called, and the pending */
/* events, if needed, will be processed in a subsequent request. */
/* Just wait until there's an unsubmitted req. This will happen almost
* immediately as one of the 2 outstanding requests is about to return.
* When this happens, uv__fast_poll_process_poll_req will be called, and
* the pending events, if needed, will be processed in a subsequent
* request. */
return;
}
/* Setting Exclusive to TRUE makes the other poll request return if there */
/* is any. */
/* Setting Exclusive to TRUE makes the other poll request return if there is
* any. */
afd_poll_info->Exclusive = TRUE;
afd_poll_info->NumberOfHandles = 1;
afd_poll_info->Timeout.QuadPart = INT64_MAX;
......@@ -218,7 +218,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
if ((handle->events & ~(handle->submitted_events_1 |
handle->submitted_events_2)) != 0) {
uv__fast_poll_submit_poll_req(loop, handle);
} else if ((handle->flags & UV__HANDLE_CLOSING) &&
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
uv_want_endgame(loop, (uv_handle_t*) handle);
......@@ -228,7 +228,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert(handle->type == UV_POLL);
assert(!(handle->flags & UV__HANDLE_CLOSING));
assert(!(handle->flags & UV_HANDLE_CLOSING));
assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
handle->events = events;
......@@ -257,8 +257,8 @@ static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return 0;
} else {
/* Cancel outstanding poll requests by executing another, unique poll */
/* request that forces the outstanding ones to return. */
/* Cancel outstanding poll requests by executing another, unique poll
* request that forces the outstanding ones to return. */
return uv__fast_poll_cancel_poll_req(loop, handle);
}
}
......@@ -316,9 +316,8 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
return INVALID_SOCKET;
}
/* If we didn't (try) to create a peer socket yet, try to make one. Don't */
/* try again if the peer socket creation failed earlier for the same */
/* protocol. */
/* If we didn't (try) to create a peer socket yet, try to make one. Don't try
* again if the peer socket creation failed earlier for the same protocol. */
peer_socket = loop->poll_peer_sockets[index];
if (peer_socket == 0) {
peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
......@@ -357,8 +356,8 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
efds.fd_count = 0;
}
/* Make the select() time out after 3 minutes. If select() hangs because */
/* the user closed the socket, we will at least not hang indefinitely. */
/* Make the select() time out after 3 minutes. If select() hangs because the
* user closed the socket, we will at least not hang indefinitely. */
timeout.tv_sec = 3 * 60;
timeout.tv_usec = 0;
......@@ -462,7 +461,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
if ((handle->events & ~(handle->submitted_events_1 |
handle->submitted_events_2)) != 0) {
uv__slow_poll_submit_poll_req(loop, handle);
} else if ((handle->flags & UV__HANDLE_CLOSING) &&
} else if ((handle->flags & UV_HANDLE_CLOSING) &&
handle->submitted_events_1 == 0 &&
handle->submitted_events_2 == 0) {
uv_want_endgame(loop, (uv_handle_t*) handle);
......@@ -472,7 +471,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
assert(handle->type == UV_POLL);
assert(!(handle->flags & UV__HANDLE_CLOSING));
assert(!(handle->flags & UV_HANDLE_CLOSING));
assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
handle->events = events;
......@@ -522,10 +521,10 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
return uv_translate_sys_error(WSAGetLastError());
/* Try to obtain a base handle for the socket. This increases this chances */
/* that we find an AFD handle and are able to use the fast poll mechanism. */
/* This will always fail on windows XP/2k3, since they don't support the */
/* SIO_BASE_HANDLE ioctl. */
/* Try to obtain a base handle for the socket. This increases this chances that
* we find an AFD handle and are able to use the fast poll mechanism. This will
* always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE
* ioctl. */
#ifndef NDEBUG
base_socket = INVALID_SOCKET;
#endif
......@@ -557,9 +556,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
return uv_translate_sys_error(WSAGetLastError());
}
/* Get the peer socket that is needed to enable fast poll. If the returned */
/* value is NULL, the protocol is not implemented by MSAFD and we'll have */
/* to use slow mode. */
/* Get the peer socket that is needed to enable fast poll. If the returned
* value is NULL, the protocol is not implemented by MSAFD and we'll have to
* use slow mode. */
peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
if (peer_socket != INVALID_SOCKET) {
......@@ -634,7 +633,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
assert(handle->flags & UV__HANDLE_CLOSING);
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
assert(handle->submitted_events_1 == 0);
......
......@@ -103,12 +103,12 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
DWORD client_access = 0;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
int err;
int overlap;
if (flags & UV_READABLE_PIPE) {
/* The server needs inbound access too, otherwise CreateNamedPipe() */
/* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */
/* probe the state of the write buffer when we're trying to shutdown */
/* the pipe. */
/* The server needs inbound access too, otherwise CreateNamedPipe() won't
* give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
* state of the write buffer when we're trying to shutdown the pipe. */
server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
}
......@@ -131,12 +131,13 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
child_pipe = CreateFileA(pipe_name,
client_access,
0,
&sa,
OPEN_EXISTING,
server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0,
overlap ? FILE_FLAG_OVERLAPPED : 0,
NULL);
if (child_pipe == INVALID_HANDLE_VALUE) {
err = GetLastError();
......@@ -159,8 +160,8 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
}
#endif
/* Do a blocking ConnectNamedPipe. This should not block because we have */
/* both ends of the pipe created. */
/* Do a blocking ConnectNamedPipe. This should not block because we have both
* ends of the pipe created. */
if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
if (GetLastError() != ERROR_PIPE_CONNECTED) {
err = GetLastError();
......@@ -194,11 +195,11 @@ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
HANDLE current_process;
/* _get_osfhandle will sometimes return -2 in case of an error. This seems */
/* to happen when fd <= 2 and the process' corresponding stdio handle is */
/* set to NULL. Unfortunately DuplicateHandle will happily duplicate */
/* (HANDLE) -2, so this situation goes unnoticed until someone tries to */
/* use the duplicate. Therefore we filter out known-invalid handles here. */
/* _get_osfhandle will sometimes return -2 in case of an error. This seems to
* happen when fd <= 2 and the process' corresponding stdio handle is set to
* NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so
* this situation goes unnoticed until someone tries to use the duplicate.
* Therefore we filter out known-invalid handles here. */
if (handle == INVALID_HANDLE_VALUE ||
handle == NULL ||
handle == (HANDLE) -2) {
......@@ -284,8 +285,8 @@ int uv__stdio_create(uv_loop_t* loop,
return ERROR_OUTOFMEMORY;
}
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */
/* clean up on failure. */
/* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean
* up on failure. */
CHILD_STDIO_COUNT(buffer) = count;
for (i = 0; i < count; i++) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
......@@ -303,12 +304,12 @@ int uv__stdio_create(uv_loop_t* loop,
switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
UV_INHERIT_STREAM)) {
case UV_IGNORE:
/* Starting a process with no stdin/stout/stderr can confuse it. */
/* So no matter what the user specified, we make sure the first */
/* three FDs are always open in their typical modes, e.g. stdin */
/* be readable and stdout/err should be writable. For FDs > 2, don't */
/* do anything - all handles in the stdio buffer are initialized with */
/* INVALID_HANDLE_VALUE, which should be okay. */
/* Starting a process with no stdin/stout/stderr can confuse it. So no
* matter what the user specified, we make sure the first three FDs are
* always open in their typical modes, e. g. stdin be readable and
* stdout/err should be writable. For FDs > 2, don't do anything - all
* handles in the stdio buffer are initialized with.
* INVALID_HANDLE_VALUE, which should be okay. */
if (i <= 2) {
DWORD access = (i == 0) ? FILE_GENERIC_READ :
FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
......@@ -323,14 +324,14 @@ int uv__stdio_create(uv_loop_t* loop,
break;
case UV_CREATE_PIPE: {
/* Create a pair of two connected pipe ends; one end is turned into */
/* an uv_pipe_t for use by the parent. The other one is given to */
/* the child. */
/* Create a pair of two connected pipe ends; one end is turned into an
* uv_pipe_t for use by the parent. The other one is given to the
* child. */
uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
HANDLE child_pipe = INVALID_HANDLE_VALUE;
/* Create a new, connected pipe pair. stdio[i].stream should point */
/* to an uninitialized, but not connected pipe handle. */
/* Create a new, connected pipe pair. stdio[i]. stream should point to
* an uninitialized, but not connected pipe handle. */
assert(fdopt.data.stream->type == UV_NAMED_PIPE);
assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
......@@ -354,8 +355,8 @@ int uv__stdio_create(uv_loop_t* loop,
/* Make an inheritable duplicate of the handle. */
err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
if (err) {
/* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */
/* error. */
/* If fdopt. data. fd is not valid and fd <= 2, then ignore the
* error. */
if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
......@@ -418,8 +419,8 @@ int uv__stdio_create(uv_loop_t* loop,
if (stream_handle == NULL ||
stream_handle == INVALID_HANDLE_VALUE) {
/* The handle is already closed, or not yet created, or the */
/* stream type is not supported. */
/* The handle is already closed, or not yet created, or the stream
* type is not supported. */
err = ERROR_NOT_SUPPORTED;
goto error;
}
......
......@@ -360,8 +360,8 @@ static WCHAR* search_path(const WCHAR *file,
return NULL;
}
/* Find the start of the filename so we can split the directory from the */
/* name. */
/* Find the start of the filename so we can split the directory from the
* name. */
for (file_name_start = (WCHAR*)file + file_len;
file_name_start > file
&& file_name_start[-1] != L'\\'
......@@ -556,8 +556,8 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
arg_count++;
}
/* Adjust for potential quotes. Also assume the worst-case scenario */
/* that every character needs escaping, so we need twice as much space. */
/* Adjust for potential quotes. Also assume the worst-case scenario that
* every character needs escaping, so we need twice as much space. */
dst_len = dst_len * 2 + arg_count * 2;
/* Allocate buffer for the final command line. */
......@@ -831,8 +831,13 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
*/
static WCHAR* find_path(WCHAR *env) {
for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
if (wcsncmp(env, L"PATH=", 5) == 0)
if ((env[0] == L'P' || env[0] == L'p') &&
(env[1] == L'A' || env[1] == L'a') &&
(env[2] == L'T' || env[2] == L't') &&
(env[3] == L'H' || env[3] == L'h') &&
(env[4] == L'=')) {
return &env[5];
}
}
return NULL;
......@@ -865,9 +870,9 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
assert(handle->exit_cb_pending);
handle->exit_cb_pending = 0;
/* If we're closing, don't call the exit callback. Just schedule a close */
/* callback now. */
if (handle->flags & UV__HANDLE_CLOSING) {
/* If we're closing, don't call the exit callback. Just schedule a close
* callback now. */
if (handle->flags & UV_HANDLE_CLOSING) {
uv_want_endgame(loop, (uv_handle_t*) handle);
return;
}
......@@ -878,14 +883,14 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
handle->wait_handle = INVALID_HANDLE_VALUE;
}
/* Set the handle to inactive: no callbacks will be made after the exit */
/* callback.*/
/* Set the handle to inactive: no callbacks will be made after the exit
* callback. */
uv__handle_stop(handle);
if (GetExitCodeProcess(handle->process_handle, &status)) {
exit_code = status;
} else {
/* Unable to to obtain the exit code. This should never happen. */
/* Unable to obtain the exit code. This should never happen. */
exit_code = uv_translate_sys_error(GetLastError());
}
......@@ -900,8 +905,8 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
uv__handle_closing(handle);
if (handle->wait_handle != INVALID_HANDLE_VALUE) {
/* This blocks until either the wait was cancelled, or the callback has */
/* completed. */
/* This blocks until either the wait was cancelled, or the callback has
* completed. */
BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
if (!r) {
/* This should never happen, and if it happens, we can't recover... */
......@@ -919,7 +924,7 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
assert(!handle->exit_cb_pending);
assert(handle->flags & UV__HANDLE_CLOSING);
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
/* Clean-up the process handle. */
......@@ -1104,14 +1109,13 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
/* Spawn succeeded */
/* Beyond this point, failure is reported asynchronously. */
/* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
/* If the process isn't spawned as detached, assign to the global job */
/* object so windows will kill it when the parent process dies. */
/* If the process isn't spawned as detached, assign to the global job object
* so windows will kill it when the parent process dies. */
if (!(options->flags & UV_PROCESS_DETACHED)) {
uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
......@@ -1138,7 +1142,8 @@ int uv_spawn(uv_loop_t* loop,
if (fdopt->flags & UV_CREATE_PIPE &&
fdopt->data.stream->type == UV_NAMED_PIPE &&
((uv_pipe_t*) fdopt->data.stream)->ipc) {
((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId;
((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =
info.dwProcessId;
}
}
......@@ -1154,8 +1159,8 @@ int uv_spawn(uv_loop_t* loop,
assert(!err);
/* Make the handle active. It will remain active until the exit callback */
/* is made or the handle is closed, whichever happens first. */
/* Make the handle active. It will remain active until the exit callback is
* made or the handle is closed, whichever happens first. */
uv__handle_start(process);
/* Cleanup, whether we succeeded or failed. */
......@@ -1186,16 +1191,16 @@ static int uv__kill(HANDLE process_handle, int signum) {
case SIGTERM:
case SIGKILL:
case SIGINT: {
/* Unconditionally terminate the process. On Windows, killed processes */
/* normally return 1. */
/* Unconditionally terminate the process. On Windows, killed processes
* normally return 1. */
DWORD status;
int err;
if (TerminateProcess(process_handle, 1))
return 0;
/* If the process already exited before TerminateProcess was called, */
/* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
/* If the process already exited before TerminateProcess was called,.
* TerminateProcess will fail with ERROR_ACCESS_DENIED. */
err = GetLastError();
if (err == ERROR_ACCESS_DENIED &&
GetExitCodeProcess(process_handle, &status) &&
......
......@@ -47,13 +47,13 @@ void uv_signals_init(void) {
static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
/* Compare signums first so all watchers with the same signnum end up */
/* adjacent. */
/* Compare signums first so all watchers with the same signnum end up
* adjacent. */
if (w1->signum < w2->signum) return -1;
if (w1->signum > w2->signum) return 1;
/* Sort by loop pointer, so we can easily look up the first item after */
/* { .signum = x, .loop = NULL } */
/* Sort by loop pointer, so we can easily look up the first item after
* { .signum = x, .loop = NULL }. */
if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
......@@ -90,7 +90,7 @@ int uv__signal_dispatch(int signum) {
unsigned long previous = InterlockedExchange(
(volatile LONG*) &handle->pending_signum, signum);
if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED)
if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED)
continue;
if (!previous) {
......@@ -98,8 +98,8 @@ int uv__signal_dispatch(int signum) {
}
dispatched = 1;
if (handle->flags & UV__SIGNAL_ONE_SHOT)
handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED;
if (handle->flags & UV_SIGNAL_ONE_SHOT)
handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED;
}
LeaveCriticalSection(&uv__signal_lock);
......@@ -118,10 +118,10 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
case CTRL_CLOSE_EVENT:
if (uv__signal_dispatch(SIGHUP)) {
/* Windows will terminate the process after the control handler */
/* returns. After that it will just terminate our process. Therefore */
/* block the signal handler so the main loop has some time to pick */
/* up the signal and do something for a few seconds. */
/* Windows will terminate the process after the control handler
* returns. After that it will just terminate our process. Therefore
* block the signal handler so the main loop has some time to pick up
* the signal and do something for a few seconds. */
Sleep(INFINITE);
return TRUE;
}
......@@ -129,8 +129,8 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
/* These signals are only sent to services. Services have their own */
/* notification mechanism, so there's no point in handling these. */
/* These signals are only sent to services. Services have their own
* notification mechanism, so there's no point in handling these. */
default:
/* We don't handle these. */
......@@ -193,10 +193,10 @@ int uv__signal_start(uv_signal_t* handle,
if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
return UV_EINVAL;
/* Short circuit: if the signal watcher is already watching {signum} don't */
/* go through the process of deregistering and registering the handler. */
/* Additionally, this avoids pending signals getting lost in the (small) */
/* time frame that handle->signum == 0. */
/* Short circuit: if the signal watcher is already watching {signum} don't go
* through the process of deregistering and registering the handler.
* Additionally, this avoids pending signals getting lost in the (small) time
* frame that handle->signum == 0. */
if (signum == handle->signum) {
handle->signal_cb = signal_cb;
return 0;
......@@ -213,7 +213,7 @@ int uv__signal_start(uv_signal_t* handle,
handle->signum = signum;
if (oneshot)
handle->flags |= UV__SIGNAL_ONE_SHOT;
handle->flags |= UV_SIGNAL_ONE_SHOT;
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
......@@ -237,16 +237,16 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
(volatile LONG*) &handle->pending_signum, 0);
assert(dispatched_signum != 0);
/* Check if the pending signal equals the signum that we are watching for. */
/* These can get out of sync when the handler is stopped and restarted */
/* while the signal_req is pending. */
/* Check if the pending signal equals the signum that we are watching for.
* These can get out of sync when the handler is stopped and restarted while
* the signal_req is pending. */
if (dispatched_signum == handle->signum)
handle->signal_cb(handle, dispatched_signum);
if (handle->flags & UV__SIGNAL_ONE_SHOT)
if (handle->flags & UV_SIGNAL_ONE_SHOT)
uv_signal_stop(handle);
if (handle->flags & UV__HANDLE_CLOSING) {
if (handle->flags & UV_HANDLE_CLOSING) {
/* When it is closing, it must be stopped at this point. */
assert(handle->signum == 0);
uv_want_endgame(loop, (uv_handle_t*) handle);
......@@ -265,7 +265,7 @@ void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) {
void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
assert(handle->flags & UV__HANDLE_CLOSING);
assert(handle->flags & UV_HANDLE_CLOSING);
assert(!(handle->flags & UV_HANDLE_CLOSED));
assert(handle->signum == 0);
......
......@@ -105,12 +105,10 @@ int uv_read_stop(uv_stream_t* handle) {
err = 0;
if (handle->type == UV_TTY) {
err = uv_tty_read_stop((uv_tty_t*) handle);
} else if (handle->type == UV_NAMED_PIPE) {
uv__pipe_read_stop((uv_pipe_t*) handle);
} else {
if (handle->type == UV_NAMED_PIPE) {
uv__pipe_stop_read((uv_pipe_t*) handle);
} else {
handle->flags &= ~UV_HANDLE_READING;
}
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(handle->loop, handle);
}
......@@ -136,7 +134,8 @@ int uv_write(uv_write_t* req,
err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
break;
case UV_NAMED_PIPE:
err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb);
err = uv__pipe_write(
loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);
break;
case UV_TTY:
err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
......@@ -158,25 +157,18 @@ int uv_write2(uv_write_t* req,
uv_loop_t* loop = handle->loop;
int err;
if (!(handle->flags & UV_HANDLE_WRITABLE)) {
return UV_EPIPE;
if (send_handle == NULL) {
return uv_write(req, handle, bufs, nbufs, cb);
}
err = ERROR_INVALID_PARAMETER;
switch (handle->type) {
case UV_NAMED_PIPE:
err = uv_pipe_write2(loop,
req,
(uv_pipe_t*) handle,
bufs,
nbufs,
send_handle,
cb);
break;
default:
assert(0);
if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) {
return UV_EINVAL;
} else if (!(handle->flags & UV_HANDLE_WRITABLE)) {
return UV_EPIPE;
}
err = uv__pipe_write(
loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb);
return uv_translate_sys_error(err);
}
......@@ -184,7 +176,7 @@ int uv_write2(uv_write_t* req,
int uv_try_write(uv_stream_t* stream,
const uv_buf_t bufs[],
unsigned int nbufs) {
if (stream->flags & UV__HANDLE_CLOSING)
if (stream->flags & UV_HANDLE_CLOSING)
return UV_EBADF;
if (!(stream->flags & UV_HANDLE_WRITABLE))
return UV_EPIPE;
......
This diff is collapsed.
......@@ -26,26 +26,6 @@
#include "uv.h"
#include "internal.h"
#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
static int uv_cond_fallback_init(uv_cond_t* cond);
static void uv_cond_fallback_destroy(uv_cond_t* cond);
static void uv_cond_fallback_signal(uv_cond_t* cond);
static void uv_cond_fallback_broadcast(uv_cond_t* cond);
static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
static int uv_cond_fallback_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout);
static int uv_cond_condvar_init(uv_cond_t* cond);
static void uv_cond_condvar_destroy(uv_cond_t* cond);
static void uv_cond_condvar_signal(uv_cond_t* cond);
static void uv_cond_condvar_broadcast(uv_cond_t* cond);
static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex);
static int uv_cond_condvar_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout);
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
DWORD result;
HANDLE existing_event, created_event;
......@@ -69,8 +49,8 @@ static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
guard->ran = 1;
} else {
/* We lost the race. Destroy the event we created and wait for the */
/* existing one to become signaled. */
/* We lost the race. Destroy the event we created and wait for the existing
* one to become signaled. */
CloseHandle(created_event);
result = WaitForSingleObject(existing_event, INFINITE);
assert(result == WAIT_OBJECT_0);
......@@ -377,220 +357,35 @@ int uv_sem_trywait(uv_sem_t* sem) {
}
/* This condition variable implementation is based on the SetEvent solution
* (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
* We could not use the SignalObjectAndWait solution (section 3.4) because
* it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
* uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
*/
static int uv_cond_fallback_init(uv_cond_t* cond) {
int err;
/* Initialize the count to 0. */
cond->fallback.waiters_count = 0;
InitializeCriticalSection(&cond->fallback.waiters_count_lock);
/* Create an auto-reset event. */
cond->fallback.signal_event = CreateEvent(NULL, /* no security */
FALSE, /* auto-reset event */
FALSE, /* non-signaled initially */
NULL); /* unnamed */
if (!cond->fallback.signal_event) {
err = GetLastError();
goto error2;
}
/* Create a manual-reset event. */
cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */
TRUE, /* manual-reset */
FALSE, /* non-signaled */
NULL); /* unnamed */
if (!cond->fallback.broadcast_event) {
err = GetLastError();
goto error;
}
return 0;
error:
CloseHandle(cond->fallback.signal_event);
error2:
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
return uv_translate_sys_error(err);
}
static int uv_cond_condvar_init(uv_cond_t* cond) {
pInitializeConditionVariable(&cond->cond_var);
return 0;
}
int uv_cond_init(uv_cond_t* cond) {
uv__once_init();
if (HAVE_CONDVAR_API())
return uv_cond_condvar_init(cond);
else
return uv_cond_fallback_init(cond);
}
static void uv_cond_fallback_destroy(uv_cond_t* cond) {
if (!CloseHandle(cond->fallback.broadcast_event))
abort();
if (!CloseHandle(cond->fallback.signal_event))
abort();
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
}
static void uv_cond_condvar_destroy(uv_cond_t* cond) {
/* nothing to do */
InitializeConditionVariable(&cond->cond_var);
return 0;
}
void uv_cond_destroy(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_destroy(cond);
else
uv_cond_fallback_destroy(cond);
}
static void uv_cond_fallback_signal(uv_cond_t* cond) {
int have_waiters;
/* Avoid race conditions. */
EnterCriticalSection(&cond->fallback.waiters_count_lock);
have_waiters = cond->fallback.waiters_count > 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
if (have_waiters)
SetEvent(cond->fallback.signal_event);
}
static void uv_cond_condvar_signal(uv_cond_t* cond) {
pWakeConditionVariable(&cond->cond_var);
/* nothing to do */
(void) &cond;
}
void uv_cond_signal(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_signal(cond);
else
uv_cond_fallback_signal(cond);
}
static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
int have_waiters;
/* Avoid race conditions. */
EnterCriticalSection(&cond->fallback.waiters_count_lock);
have_waiters = cond->fallback.waiters_count > 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
if (have_waiters)
SetEvent(cond->fallback.broadcast_event);
}
static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
pWakeAllConditionVariable(&cond->cond_var);
WakeConditionVariable(&cond->cond_var);
}
void uv_cond_broadcast(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_broadcast(cond);
else
uv_cond_fallback_broadcast(cond);
}
static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
DWORD dwMilliseconds) {
DWORD result;
int last_waiter;
HANDLE handles[2] = {
cond->fallback.signal_event,
cond->fallback.broadcast_event
};
/* Avoid race conditions. */
EnterCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.waiters_count++;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
/* It's ok to release the <mutex> here since Win32 manual-reset events */
/* maintain state when used with <SetEvent>. This avoids the "lost wakeup" */
/* bug. */
uv_mutex_unlock(mutex);
/* Wait for either event to become signaled due to <uv_cond_signal> being */
/* called or <uv_cond_broadcast> being called. */
result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
EnterCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.waiters_count--;
last_waiter = result == WAIT_OBJECT_0 + 1
&& cond->fallback.waiters_count == 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
/* Some thread called <pthread_cond_broadcast>. */
if (last_waiter) {
/* We're the last waiter to be notified or to stop waiting, so reset the */
/* the manual-reset event. */
ResetEvent(cond->fallback.broadcast_event);
}
/* Reacquire the <mutex>. */
uv_mutex_lock(mutex);
if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
return 0;
if (result == WAIT_TIMEOUT)
return UV_ETIMEDOUT;
abort();
return -1; /* Satisfy the compiler. */
}
static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (uv_cond_wait_helper(cond, mutex, INFINITE))
abort();
}
static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
abort();
WakeAllConditionVariable(&cond->cond_var);
}
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_wait(cond, mutex);
else
uv_cond_fallback_wait(cond, mutex);
}
static int uv_cond_fallback_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout) {
return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
abort();
}
static int uv_cond_condvar_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout) {
if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
return 0;
if (GetLastError() != ERROR_TIMEOUT)
abort();
......@@ -598,15 +393,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond,
}
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
uint64_t timeout) {
if (HAVE_CONDVAR_API())
return uv_cond_condvar_timedwait(cond, mutex, timeout);
else
return uv_cond_fallback_timedwait(cond, mutex, timeout);
}
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
int err;
......
This diff is collapsed.
This diff is collapsed.
......@@ -74,8 +74,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
return GetLastError();
}
/* Associate it with the I/O completion port. */
/* Use uv_handle_t pointer as completion key. */
/* Associate it with the I/O completion port. Use uv_handle_t pointer as
* completion key. */
if (CreateIoCompletionPort((HANDLE)socket,
loop->iocp,
(ULONG_PTR)socket,
......@@ -83,31 +83,28 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
return GetLastError();
}
if (pSetFileCompletionNotificationModes) {
/* All known Windows that support SetFileCompletionNotificationModes */
/* have a bug that makes it impossible to use this function in */
/* conjunction with datagram sockets. We can work around that but only */
/* if the user is using the default UDP driver (AFD) and has no other */
/* LSPs stacked on top. Here we check whether that is the case. */
opt_len = (int) sizeof info;
if (getsockopt(socket,
SOL_SOCKET,
SO_PROTOCOL_INFOW,
(char*) &info,
&opt_len) == SOCKET_ERROR) {
return GetLastError();
}
/* All known Windows that support SetFileCompletionNotificationModes have a
* bug that makes it impossible to use this function in conjunction with
* datagram sockets. We can work around that but only if the user is using
* the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
* we check whether that is the case. */
opt_len = (int) sizeof info;
if (getsockopt(
socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
SOCKET_ERROR) {
return GetLastError();
}
if (info.ProtocolChain.ChainLen == 1) {
if (pSetFileCompletionNotificationModes((HANDLE)socket,
FILE_SKIP_SET_EVENT_ON_HANDLE |
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
handle->func_wsarecv = uv_wsarecv_workaround;
handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
return GetLastError();
}
if (info.ProtocolChain.ChainLen == 1) {
if (SetFileCompletionNotificationModes(
(HANDLE) socket,
FILE_SKIP_SET_EVENT_ON_HANDLE |
FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
handle->func_wsarecv = uv_wsarecv_workaround;
handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
} else if (GetLastError() != ERROR_INVALID_FUNCTION) {
return GetLastError();
}
}
......@@ -191,7 +188,7 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
if (handle->flags & UV__HANDLE_CLOSING &&
if (handle->flags & UV_HANDLE_CLOSING &&
handle->reqs_pending == 0) {
assert(!(handle->flags & UV_HANDLE_CLOSED));
uv__handle_close(handle);
......@@ -245,12 +242,12 @@ static int uv_udp_maybe_bind(uv_udp_t* handle,
handle->flags |= UV_HANDLE_IPV6;
if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
/* On windows IPV6ONLY is on by default. */
/* If the user doesn't specify it libuv turns it off. */
/* On windows IPV6ONLY is on by default. If the user doesn't specify it
* libuv turns it off. */
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
/* available, or when run on XP/2003 which have no support for dualstack */
/* sockets. For now we're silently ignoring the error. */
/* TODO: how to handle errors? This may fail if there is no ipv4 stack
* available, or when run on XP/2003 which have no support for dualstack
* sockets. For now we're silently ignoring the error. */
setsockopt(handle->socket,
IPPROTO_IPV6,
IPV6_V6ONLY,
......@@ -386,8 +383,8 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
handle->recv_cb = recv_cb;
handle->alloc_cb = alloc_cb;
/* If reading was stopped and then started again, there could still be a */
/* recv request pending. */
/* If reading was stopped and then started again, there could still be a recv
* request pending. */
if (!(handle->flags & UV_HANDLE_READ_PENDING))
uv_udp_queue_recv(loop, handle);
......@@ -467,19 +464,19 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
if (!REQ_SUCCESS(req)) {
DWORD err = GET_REQ_SOCK_ERROR(req);
if (err == WSAEMSGSIZE) {
/* Not a real error, it just indicates that the received packet */
/* was bigger than the receive buffer. */
/* Not a real error, it just indicates that the received packet was
* bigger than the receive buffer. */
} else if (err == WSAECONNRESET || err == WSAENETRESET) {
/* A previous sendto operation failed; ignore this error. If */
/* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */
/* MSG_PEEK flag to clear out the error queue. For nonzero reads, */
/* immediately queue a new receive. */
/* A previous sendto operation failed; ignore this error. If zero-reading
* we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
* clear out the error queue. For nonzero reads, immediately queue a new
* receive. */
if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
goto done;
}
} else {
/* A real error occurred. Report the error to the user only if we're */
/* currently reading. */
/* A real error occurred. Report the error to the user only if we're
* currently reading. */
if (handle->flags & UV_HANDLE_READING) {
uv_udp_recv_stop(handle);
buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
......@@ -503,8 +500,8 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
struct sockaddr_storage from;
int from_len;
/* Do a nonblocking receive */
/* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
/* Do a nonblocking receive.
* TODO: try to read multiple datagrams at once. FIONREAD maybe? */
buf = uv_buf_init(NULL, 0);
handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
if (buf.base == NULL || buf.len == 0) {
......@@ -741,7 +738,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
return UV_EINVAL;
}
if (!(handle->flags & UV_HANDLE_BOUND))
if (handle->socket == INVALID_SOCKET)
return UV_EBADF;
if (addr_st.ss_family == AF_INET) {
......@@ -772,7 +769,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
BOOL optval = (BOOL) value;
if (!(handle->flags & UV_HANDLE_BOUND))
if (handle->socket == INVALID_SOCKET)
return UV_EBADF;
if (setsockopt(handle->socket,
......@@ -818,7 +815,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
return UV_EINVAL; \
} \
\
if (!(handle->flags & UV_HANDLE_BOUND)) \
if (handle->socket == INVALID_SOCKET) \
return UV_EBADF; \
\
if (!(handle->flags & UV_HANDLE_IPV6)) { \
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment