Add a process options flag to enable the optional behavior. Most users
are likely recommended to set this flag by default, but it was deemed
potentially breaking to set it by default in libuv.
Co-authored-by: Kyle Edwards <kyle.edwards@kitware.com>
Since `io_uring` support was added, libuv's signal handler randomly
segfaults on ppc64 when interrupting `epoll_pwait`. Disable it
pending further investigation.
Issue: https://github.com/libuv/libuv/issues/4283
Solaris claimed it supported the TCP-Alives mechanism,
but TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT were not
available on Solaris until the latest version 11.4.
Therefore, we need to simulate the TCP-Alives mechanism on
other platforms via TCP_KEEPALIVE_THRESHOLD + TCP_KEEPALIVE_ABORT_THRESHOLD.
The `\0` character has no special significance in abstract sockets, so
the addrlen field in both `bind()` and `connect()` should take that into
account.
Calling `uv_timer_start(h, cb, 0, 0)` from a timer callback resulted in
the timer running immediately because it was inserted at the front of
the timer heap.
If the callback did that every time, libuv would effectively busy-loop
in `uv__run_timers()` and never make forward progress.
Work around that by collecting all expired timers into a queue and only
running their callback afterwards.
Fixes: https://github.com/libuv/libuv/issues/4245
Co-authored-by: Ben Noordhuis <info@bnoordhuis.nl>
Introduced long ago for old Linux/libc flavors libuv no longer supports.
We include <ifaddrs.h> unconditionally elsewhere so there is no point in
special-casing it here.
Fixes: https://github.com/libuv/libuv/issues/4242
Passing a socket name without a trailing nul byte to uv_pipe_bind2() or
(on Windows) uv_pipe_connect2() resulted in reading beyond the end of
the name buffer when copying or converting it.
Fix that by copying the socket name to temporary storage first and add
the trailing nul byte explicitly.
Add a check for embedded nul bytes in the socket name.
Fix a small memory leak in the Windows error path of uv_pipe_bind2().
There is no length at which this gets truncated on Windows. The
underlying file system will just not successfully connect to a longer
path (in WTF-16 characters), which will return an error asynchronously
with the existing API.
Refs: #4040
This was incorrectly dropped by #4030, where previously connecting to ""
might fail eventually, now instead it would return EINVAL and then fail
to initialize the struct or call the callback.
Add uv_thread_setpriority for setting priority for threads created by
uv_thread_create. Add uv_thread_getpriority for getting thread priority.
For Linux by default, if the scheduling policy is SCHED_OTHER and the
priority is 0, we need to set the nice value.
Fixes: https://github.com/libuv/libuv/issues/4051
Passing this to uv__is_ipv6_link_local() is causing a segmentation
fault. Note that the documentation for getifaddrs() explicitly states
that this value may be NULL.
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
uv_os_uname() on Windows queries the registry value "HKEY_LOCAL_MACHINE\
SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName" to fill
uv_utsname_t. If calling application was compiled for x86 and run on a
x86_64 host, that query is redirected to "Computer\HKEY_LOCAL_MACHINE\
SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\ProductName"
instead.
For whatever reason, the value of 'ProductName' in the 32-bit registry
section on 64-bit Windows sometimes differs from the 64-bit equivalent
value and is inaccurate (e.g. containing the data
"Windows 10 Enterprise" while the 64-bit value accurately contains
"Windows 10 Pro").
Adds the 'KEY_WOW64_64KEY' security descriptor when opening the
appropriate registry key so that the value of ProductName is always
taken from the primary registry on 64-bit systems, regardless of
compiled architecture. The descriptor is safely ignored on 32-bit hosts.
As promised in #2970, this attempts to migrate code to a common set of
utilities in a common place in the code and use them everywhere. This
also exports the functionality, since the Windows API with
WideCharToMultiByte is fairly verbose relative to what libuv and
libuv's clients typically need, so it is useful not to require clients
to reimplement this conversion logic unnecessarily (and because Windows
is not 64-bit ready here, but this implementation is.)
The workaround for preadv/pwritev is needed only
for Solaris, not illumos, so avoid it on illumos.
Haiku R1/prebeta5 (and later) provide preadv and
pwritev, so only use workaround on lower versions.
Signed-off-by: Jeffrey H. Johnson <trnsz@pobox.com>
Implement in terms of pread/pwrite and only try to read/write the first
buffer. Callers are supposed to handle partial reads and libuv takes
care of partial writes.
(Our own fs_read_bufs test doesn't but that's fine because this commit
is a fix-up for unsupported platforms that aren't in our CI matrix.)
Fixes: https://github.com/libuv/libuv/issues/4176
Under heavy workloads pthread_cond_wait on macOS can return EINVAL while
all the input parameters are correct.
As it happens due to a syscall having an errno of EBUSY we can detect it
and work around it.
Fixes: https://github.com/libuv/libuv/issues/4165
We can use the |bufs| argument directly instead of always copying it
and sometimes heap-allocating it.
The same trick doesn't work for uv_fs_write() because the iterator
mutates the buffers in the list and that's visible to the caller.
Fixes: https://github.com/libuv/libuv/issues/4038
The previous implementation using si11v1cpcmodel did not return a valid
cpu model on z/OS. So use PCCA instead to correctly get the cpu model.
Co-authored-by: Wayne Zhang <shuowang.zhang@ibm.com>
Co-authored-by: Gaby Baghdadi <baghdadi@ca.ibm.com>
Co-authored-by: Jonathan Lai <jonathan.lai@ibm.com>
Fixes: https://github.com/libuv/libuv/issues/4102
Make printing handles from gdb a little easier because it doesn't always
know how to locate the stdout or stderr globals from libc.
With this commit `call uv_print_all_handles(0, 0)` prints the handles
from the default loop to stderr.
XNU kernels anno ~2010 had a data corrruption bug where concurrent
write and pwrite calls sometimes resulted in blocks of zeroes being
written instead of the actual data.
Libuv works around that by serializing all writes with a process-wide
mutex, meaning oncurrent writes (for all files, not just single files)
have a concurrency of 1. Obviously that's not great for performance.
Modern day macOS no longer has this bug, so remove the workaround.
Make sure this handle is functional. The Windows kernel seems to have a
bug that if the first use of AssignProcessToJobObject is for a Windows
Store program, subsequent attempts to use the handle with fail with
INVALID_PARAMETER (87). This is possilby because all uses of the handle
must be for the same Terminal Services session. We can ensure it is
tied to our current session now by adding ourself to it. We could
remove ourself afterwards, but there doesn't seem to be a reason to.
Secondly, we start the process suspended so that we can make sure we
added it to the job control object before it does anything itself (such
as launch more jobs or exit).
Fixes: https://github.com/JuliaLang/julia/issues/51461
If a signal was received but was not dispatched before fork then
caught_signals counter should be reset. Closing of signal pipe makes
impossible to receive the signal that was counted.
There is no need in this signal because it was sent to parent process
Fixes: https://github.com/libuv/libuv/issues/3483
Adjust include order to avoid redefining `CTL_CODE`, `FILE_READ_ACCESS`,
and `FILE_WRITE_ACCESS`. Without this, compilation shows:
```
...\um\winioctl.h(273): warning C4005: 'CTL_CODE': macro redefinition
...\src\win\winapi.h(4497): note: see previous definition of 'CTL_CODE'
...\um\winioctl.h(320): warning C4005: 'FILE_READ_ACCESS': macro redefinition
...\src\win\winapi.h(4488): note: see previous definition of 'FILE_READ_ACCESS'
...\um\winioctl.h(321): warning C4005: 'FILE_WRITE_ACCESS': macro redefinition
...\src\win\winapi.h(4492): note: see previous definition of 'FILE_WRITE_ACCESS'
```
Match the implementation for linux.c to kqueue.c in the code around the
calls to kevent and epoll.
In linux.c the code was made more DRY by moving the nfds check up
(including a comment of why it's possible) and combining two if checks
into one.
In kqueue.c the assert to check the timeout when nfds == 0 has been
moved to be called directly after the EINTR check. Since it should
always be true regardless.
Ref: https://github.com/libuv/libuv/pull/3893
Ref: https://github.com/nodejs/node/issues/48490
Link-local addresses (prefix fe80::/64) don't route unless you specify
the network interface to use so make libuv do that.
Fixes: https://github.com/nodejs/node/issues/48846
Work around a poorly understood bug in older kernels where closing a
file descriptor pointing to /foo/bar results in ETXTBSY errors when
trying to execve("/foo/bar") later on.
The bug seems to have been fixed somewhere between 5.15.85 and 5.15.90.
I couldn't pinpoint the responsible commit but good candidates are the
several data race fixes.
Interestingly, it seems to manifest only when running under Docker so
the possibility of a Docker bug can't be completely ruled out either.
This commit moves uv__kernel_version() from fs.c to linux.c because the
latter now uses it more than the former.
Fixes: https://github.com/nodejs/node/issues/48444
The initial run of timers shouldn't happen if uv_stop() has been run
before uv_run() was called, and for backwards compatibility they also
shouldn't run if they have been unref'd before calling uv_run().
Apple's documentation claims ru_maxrss is reported in kilobytes but the
XNU source code suggests the actual unit is bytes, like macOS.
Fixes: https://github.com/libuv/libuv/issues/4025
Recent versions of gcc have started emitting warnings about the liberal
type casting inside the QUEUE macros. Although the warnings are false
positives, let's use them as the impetus to switch to a type-safer and
arguably cleaner approach.
Fixes: https://github.com/libuv/libuv/issues/4019
In the case of trying to write more than `IOV_MAX` buffers, the
`IORING_OP_WRITEV` operation will return `EINVAL`. As a temporal fix,
fallback to the old ways. In the future we might implement this by
linking multiple `IORING_OP_WRITEV` requests using `IOSQE_IO_LINK`.
Instead of suppressing the VLA warning, use a fixed-size buffer that is
big enough to receive at least one control message but not so big that
IBMi PASE rejects it.
When there are more than 128 concurrent cq completions the CQ ring
overflows as signaled via the `UV__IORING_SQ_CQ_OVERFLOW`. If this
happens we have to enter the kernel to get the remaining items.
This commit adds the ability to dump core when sending the `SIGQUIT`
signal on Windows. The change reads in the current registry setting for
local dumps, and attempts to write out to that location before killing
the process. See [collecting-user-mode-dumps] for registry and pathing
details. This behavior mimics that of the dumps created by the typical
Windows Error Reporting mechanism.
[collecting-user-mode-dumps]: https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps
* Revert "macos: fix source not being followed when cloning (#3941)"
This reverts commit 507f2f950d.
* Revert "darwin: bring back macos-specific copyfile(3) (#3654)"
This reverts commit d4eb276eea.
The worker pool calls all callbacks locally within the queue. So the
value of nevents doesn't properly reflect that case. Increase the number
of events directly from the worker pool's callback to correct this.
In order to properly determine if the events_waiting counter needs to be
incremented, store the timeout value at the time the event provider was
called.
Fix a valgrind warning that only manifested with clang (not gcc!) by
explicitly passing 0L instead of plain 0 as the |sigsz| argument to
io_uring_enter(). That is, pass a long instead of an int.
On x86_64, |sigsz| is passed on the stack (the other arguments are
passed in registers) but where gcc emits a `push $0` that zeroes the
entire stack slot, clang emits a `movl $0,(%rsp)` that leaves the upper
32 bits untouched.
It's academic though since we don't pass IORING_ENTER_EXT_ARG and the
kernel therefore completely ignores the argument.
Refs: https://github.com/libuv/libuv/pull/3952
Add io_uring support for several asynchronous file operations:
- read, write
- fsync, fdatasync
- stat, fstat, lstat
io_uring is used when the kernel is new enough, otherwise libuv simply
falls back to the thread pool.
Performance looks great; an 8x increase in throughput has been observed.
This work was sponsored by ISC, the Internet Systems Consortium.
Fixes: https://github.com/libuv/libuv/issues/1947
Issue observed on Solaris with ISC BIND 9.18 which reported "unable to
open route socket: unexpected error". illumos did not hit it because it
does not have SO_REUSEPORT (open RFE
https://www.illumos.org/issues/12455)
The last major distro that supported the oabi calling convention was
Debian 5 (Lenny) and that went out of support in February 2012. It seems
like a fairly safe assumption that nothing speaks oabi anymore in this
day and age.
Fixes: https://github.com/libuv/libuv/issues/3935
Replace the throw-type-safety-to-the-wind CAST() macro with an inline
function that is hopefully harder to misuse. It should make the inotify
code slightly more legible if nothing else.
The maximum number of times timers should run when uv_run() is called
with UV_RUN_ONCE and UV_RUN_NOWAIT is 1. Do that by conditionally
calling timers before entering the while loop when called with
UV_RUN_DEFAULT.
The reason to always run timers at the end of the while loop, instead of
at the beginning, is to help enforce the conceptual event loop model.
Which starts when entering the event provider (e.g. calling poll).
Other than only allowing timers to be processed once per uv_run()
execution, the only other noticeable change this will show is if all the
following are true:
* uv_run() is called with UV_RUN_NOWAIT or UV_RUN_ONCE.
* An event is waiting to be received when poll is called.
* Execution time between the call to uv_timer_start() and entering the
while loop is longer than the timeout.
If all these are true, then timers that would have executed before
entering the event provider will now be executed afterward.
Fixes: https://github.com/libuv/libuv/issues/3686
Co-authored-by: Momtchil Momtchev <momtchil@momtchev.com>
This code would previously get confused between rounds of the barrier
being called and a thread might incorrectly get stuck (deadlock) if the
next round started before that thread had exited the current round.
Avoid that by not starting the next round in++ before out-- has reached
zero indicating that all threads have left the prior round.
And fix it that on Windows by replacing the implementation with the one
from unix. There are some awkward platform-specific redirection here
with an extra malloc that is not needed on Win32, but that will be fixed
in libuv v2.
Fixes: https://github.com/libuv/libuv/issue/3872
The call to uv__cwd() always returns a new allocation. The previously
allocated utf16_buffer needs to be free'd before passing it in to
receive the next allocation.
ThreadSanitizer complains about unsynchronized access to the
handle->loop->cf_state pointer.
The warning is probably benign but the fsevents thread already knows
the pointer. It doesn't have to read it, it just needs to propagate it.
Refs: https://github.com/libuv/libuv/issues/3880
The conditional bind-to-port logic in tcp.c had an error path that
closed the socket file descriptor while it was still owned by the
uv_tcp_t handle.
Fix that by not closing the file descriptor and refactoring the code so
it is hopefully harder to get wrong in the future.
The refactoring also makes the code a little flatter, removes duplicated
code, and, arguably, is in a more idiomatic libuv style.
Fixes: https://github.com/libuv/libuv/issues/3461
Replaces: https://github.com/libuv/libuv/pull/3462
Co-authored-by: Ben Noordhuis <info@bnoordhuis.nl>
Since we are emulating this event, but are not using the pending_queue,
we need to make sure it is accounted for properly. Also DRY some of the
reset_timeout code here.
This was observed to cause a hang in certain rare cases, particularly on
M1 machines.
Do a bit of code cleanup too, since we do not need to initialize the
internal signal handling pipe if it will not be used.
The current fix (libuv#2231) was found to be slow in certain cases. This
change should improve scalabaility a bit by only incurring the spin loop
delay while closing an UV_ASYNC. It also is intended to slightly improve
the behavior after uv_loop_close is called, by parking all of the
pending flags as set, so that it will not access the loop at all (until
the uv_async_t memory is freed, which we leave still to the
responsibility of the user).
Note that this bug appears to still exist on Win32, though it's harder
to address without the refactoring done to this code on libuv master.
Takes some inspiration from https://github.com/libuv/libuv/pull/2654
Takes some inspiration from https://github.com/libuv/libuv/pull/2656
Refs: https://github.com/libuv/libuv/pull/2231
File system operations may return uid and gid values, which we may want
to pretty-print. We already have the code for getting information for
the current user, so just need to add a parameter to make it exposed for
every user. We expose information about groups in a similar manner also.
In Node.js, fs.readlink() on a non-symlink file used to throw an UNKNOWN
error on Windows. This change maps ERROR_NOT_A_REPARSE_POINT to
UV_EINVAL, so that now it throws EINVAL just like other platforms.
This is handled explicitly in `fs__readlink`, since elsewhere it might
map to EPERM instead (such as in `link`).
On Linux, CPUs can come online or go offline while uv_cpu_info() is busy
gathering data. Change uv_cpu_info() in the following ways:
1. Learn online CPUs from /proc/stat
2. Get the model name from /proc/cpuinfo when it has a matching CPU,
or default to "unknown"
3. Get speed from /sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq
when it exists, or default to 0
Before this commit, libuv read the speed from /proc/cpuinfo but that
reports the base frequency, not the actual frequency. My system has
two cores running permanently at 3.6 GHz but libuv thought all 12 ran
at 2.2 GHz.
Fixes: https://github.com/libuv/libuv/issues/2351
Fixes: https://github.com/libuv/libuv/issues/3858
Return `UV_EAGAIN` on `ERROR_OPERATION_ABORTED`.
Use the correct format for `overlapped.hEvent`.
Some refactoring to always wait for the overlapped result.
Modernize tests and some improvements.
Calling uv_fs_fstat for file types other then disk type was resulting in
error on Windows while it was retrieving data on Linux. This change
enables getting fstat for pipes and character files on Windows with data
fetched being as reasonable as possible.
A simple test is also added to check this behavior on all platforms. It
uses stdin, stdout and stderr. uv_fs_fstat needs to pass with disk files
pipes and character files (eg. console).
Refs: https://github.com/nodejs/node/issues/40006
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
The old Linux baseline was essentially RHEL 6 but that distro has been
out of support for two years now. Move to RHEL 7.
This commit also moves FreeBSD to tier 2 because it isn't actually
part of libuv's CI matrix, only Node's.
Fixes: https://github.com/libuv/libuv/issues/3822
The following metrics are now always recorded and available via the new
uv_metrics_info() API.
* loop_count: Number of event loop iterations.
* events: Total number of events processed by the event handler.
* events_waiting: Total number of events waiting in the event queue when
the event provider request was made.
Benchmarking has shown no noticeable impact recording these metrics.
PR-URL: https://github.com/libuv/libuv/pull/3749
Make unices and windows consistent when closing a pipe while it's
connecting so they all return `UV_ECANCELED`.
Avoid race condition between `pipe_connect_thread_proc()` and `uv_close()` when
accessing `handle->name`.
Fixes: https://github.com/libuv/libuv/issues/3578
This reverts commit 87f0765159 and
implements a work-around instead. This has been reported to be
unnecessary, and also returns the wrong answer (off by exactly 100x),
so it is not particularly useful.
This also reverts the bugfixes to the original PR:
Revert "darwin: fix iOS compilation and functionality"
This reverts commit 1addf9b88a.
Revert "macos: fix the cfdata length in uv__get_cpu_speed (#3356)"
This reverts commit 1e7074913e.
Revert "darwin: fix -Wsometimes-uninitialized warning"
This reverts commit 6085bcef8d.
Revert "macos: fix memleaks in uv__get_cpu_speed"
This reverts commit d2482ae121.
The expected behavior on failure to read this info is to report 0 (for
example
https://github.com/libuv/libuv/blob/8975c05d199558b0cc2e98f26ce33c6090d1
d7a1/src/unix/linux.c#L834), which is which was not the case before
this PR for macos.
However hw.cpufrequency sysctl seems to be missing on darwin/arm64
(Apple Silicon), so we instead hardcode a plausible value. This value
matches what the mach kernel will report when running Rosetta apps.
Fixes: https://github.com/libuv/libuv/issues/3642
Fixes: https://github.com/libuv/libuv/issues/2911
Refs: https://github.com/libuv/libuv/pull/2912
Backported thread affinity feature and related dependency commits
from master. It will add support for those APIs: uv_cpumask_size,
uv_thread_setaffinity, uv_thread_getaffinity.
The supported platforms are Linux, Freebsd, and Windows.
Empty implementations (returning UV_ENOTSUP) on non-supported platforms
(such as OS X and AIX).
In the old version of uv_pipe_open, the parent process ID is used
always. If the open pipe is used in the same process, the parent
process will be obtained incorrectly.
Now we first get the client pid and compare it with its own pid. If it
is the same, then get the server pid. If the two are the same, then the
pipe is from the same process.
Fixes: https://github.com/libuv/libuv/issues/3766
- unpoison results from linux system call wrappers
- unpoison results from stat/fstat/lstat to pacify clang 14
(fixed in later versions)
- add MSAN build option
- turn on MSAN CI build
I split up linux.c around 2012 for no real reason and now I'm merging
it back together, again for no real reason.
I half-jest. I like the idea of having everything together because I
practically forgot linux-inotify.c existed. It also makes io_uring
experiments a little easier.
Last but not least, it removes about 100 lines of license boilerplate.
preadv, pwritev, dup3 and utimensat all exist in 2.6.32 kernels, libuv's
minimum supported kernel.
The wrapper for utimensat was already gone, only the define remained.
uv_fs_scandir() leaked an entry when you called it on a directory with
a single entry _and_ you didn't run the iterator until UV_EOF.
Fixes: https://github.com/libuv/libuv/issues/3748
epoll.c is only used on Android and Linux after commit 5fe59726 ("sunos:
restore use of event ports") so move it back into linux-core.c
This commit removes a workaround for pre-2.6.27 kernels that don't have
the epoll_create1() system call.
Remove the TODO that says to batch up kevent(EV_DELETE) system calls.
It's unduly complicated in case of errors.
If you pass an out array to kevent(), it will store error records that
tell you which file descriptor caused the error but it also stores new
events in the array, complicating state management.
If you don't pass an out array, it simply doesn't tell you anything
except that _something_ failed. Optimistically trying batch deletion
and falling back to one-by-one deletion is probably possible but is
something of a deoptimization and also feels somewhat dangerous.
macOS has a mostly-undocumented kevent_qos() system call that accepts a
KEVENT_FLAG_ERROR_EVENTS flag that fixes the first problem but that of
course isn't portable.
Long story short, it seems like too much hassle for too little payoff.
Libuv has been doing one-by-one deletion for over a decade now and no
one complained about performance so far so let's just stick with that.
Another thread can change the working directory between calls to
GetCurrentDirectoryW().
The first call was used to determine the size of the buffer to use in
the second call. Retry if the reported size does not match the expected
size because the buffer's contents is undefined in that case.
uv_exepath() wrote the nul byte *after* the end of the buffer. It's not
necessary to write said nul byte in the first place because that was a
workaround for a bug in the Windows XP version of GetModuleFileName().
Fix uv_cwd() in the same fashion, it doesn't need the nul byte either.
Fixes: https://github.com/libuv/libuv/issues/3691
After analysis of many real-world programs I've come to conclude that
accepting in a loop is nearly always suboptimal.
1. 99.9% of the time the second accept() call fails with EAGAIN, meaning
there are no additional connections to accept. Not super expensive
in isolation but it adds up.
2. When there are more connections to accept but the listen socket is
shared between multiple processes (ex. the Node.js cluster module),
libuv's greedy behavior necessitated the UV_TCP_SINGLE_ACCEPT hack
to slow it down in order to give other processes a chance.
Accepting a single connection and relying on level-triggered polling to
get notified on the next incoming connection both simplifies the code
and optimizes for the common case.
This was a kludge for a bug in old versions (API level <= 16) of the
Android SDK.
The os390 port had a build dependency on the file but does not actually
use it so that too has been removed.
Split this off from endgame, so that it can be handled separately and
earlier, rather than trying to detect inside endgame which case we are
in. There appear to be some race conditions on the `handle` field still
however, which this does not yet attempt to address.
Some setsockopt() implememantations may return with errno of EINVAL
when the socket has been shut down already, as documented in the
Open Group Specifications Issue 7, 2018.
When this happens, reset errno and continue to mark the socket closed
and handle any callback.
Port the changes made to AIX and other unix systems in #611 to z/OS.
Defers the signal watcher that is used for process management until
after the dispatch of regular i/o watchers.
Refs: https://github.com/libuv/libuv/pull/611
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
Once the write queue is empty, we can fire the event immediately,
without needing a lot of syscalls and then waiting for the kernel to
feed us the event on the next tick. This also makes it more similar to
how it would behave if there was a write still in the queue also, which
we dispatch later in the same event loop iteration, then drain.
EINTR is explicitly documented as a possible error code of tcsetattr().
The documentation for tcgetattr() is silent on the subject but better
safe than sorry.
Fixes: https://github.com/libuv/libuv/issues/3645
The UV_ECANCELED codepath had an incorrect comment, and the
implementation was generally less robust (for example, not checking if
`cb` was NULL), so we can merge these codepaths for cleaner code.
The errno value is only meaningful if bind() fails and returns -1.
Some bind() implementations may return success but modify errno value
internally, like the socket_wrapper library used by the Samba testsuite.
This fixes an early exit bug in z/OS implementation of epoll_wait(),
resulting in some file events not being correctly captured.
The problem is that reventcount should only be incremented by 1, because
_NFDS counts as 1 even for fds with multiple revents set.
Also makes a few minor improvements to remove redundant checks.
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
Fixes an issue where under certain conditions, dynamically allocated
ip addresses, strings, and buffers were either leaking memory, being
incorrectly freed, or not performing error checks.
Also fixes an issue where the uv_interface_address_t struct was not
correctly initialized to 0, so use calloc() instead of malloc().
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
Use SIOCGIFNETMASK ioctl to retrieve the netmask for IPv4. However, this
approach is not supported for IPv6.
For IPv6 netmask, z/OS currently only provides the prefix length through
the __nif6e_prefixlen in __net_ifconf6entry_t struct, but this can be
used to calculate the IPv6 netmask similar to android implementation.
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
On z/OS, the interface address name contains EBCDIC and may be padded
with whitespaces. The whitespace padding needs to be trimmed, and the
interface address name needs to be converted from EBCDIC to ASCII.
Co-authored-by: John Barboza <jbarboza@ca.ibm.com>
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
On z/OS, fs events are implemented by registering file interest. When
closing a fs event handle, it's possible that a change notification has
already been generated. In that case, the attempt to unregister file
interest will fail with EALREADY. This will result in the fs event being
delivered even though the handle is closing, which should not happen.
Fixes: https://github.com/libuv/libuv/issues/3601
On z/OS, EPERM is returned if the process being killed is a zombie.
However, this shouldn't be treated as an error, so return 0 instead.
Co-authored-by: Muntasir Mallick <mmallick@ca.ibm.com>
Co-authored-by: Gaby Baghdadi <baghdadi@ca.ibm.com>
On NetBSD with libuv 1.44.1 we see that cmake occasionally hangs
waiting for a child process to exit, with libuv waiting forever for
`kevent` to deliver more events that never come. The child process has
already exited and is waiting to be collected with `waitpid`.
The hang occurs when the batch of events returned by one call to
`kevent` contains both a EVFILT_READ event for an fd and a later
EVFILT_PROC record for the PID with the same value as the earlier fd.
What happens is that `uv__platform_invalidate_fd` is called to
invalidate events later in the same batch for the fd, but
`uv__platform_invalidate_fd` invalidates the later EVFILT_PROC event
too because it sees the same "ident" value and does not check the
"filter" value to differentiate "ident" values that refer to fds vs.
"ident" values that refer to PIDs.
Add a check for the "filter" value to avoid confusing these two
different kinds of event "ident" values.
Previously, Windows would always defer event processing to the loop
after they were received. This could cause confusion for users who were
using prepare and idle callbacks, as seen from this bug in nodejs[^1] and
this discussion in libuv[^2], and even some discrepancies in the libuv
tests too[^3].
[^1]: https://github.com/nodejs/node/pull/42340
[^2]: https://github.com/libuv/libuv/discussions/3550
[^3]: See change to test-spawn.c in this PR
So rather than declare those usages to be wrong, we change libuv to meet
those users expectations.
Replaces: https://github.com/libuv/libuv/pull/3585
If `uv_close` was called while a connect was pending, we would fail to
release the resources for the connection, since we had not yet set the
type of the struct.
Fix a thread data-race on slow connect path code: only permitted to
write to `req` on threads, as anything else causes data race
corruption.
There seemed be a small variety of other resource management bugs in
edge cases, which turned out to make this a lot larger than initially
expected.
Refs: https://github.com/libuv/libuv/pull/3598#issuecomment-1111513567
Use MSG_CMSG_CLOEXEC on Unix-y platforms that support it (all except
macOS and SunOS spawn.)
Remove the feature test for Linux. Libuv's kernel baseline is 2.6.32
and MSG_CMSG_CLOEXEC was added in 2.6.23.
macOS 10.15 has a bug where configuring the working directory with
posix_spawn_file_actions_addchdir_np() makes posix_spawnp() fail with
ENOENT even though the executable is spawned successfully.
Co-authored-by: Ben Noordhuis <info@bnoordhuis.nl>
When the watched file is moved or removed, or an editor (e.g. vim)
renames then creates the file, the __rfim_event 156 occurs. This is an
undocumented event that should not happen, but register it as UV_RENAME
for now since it is functionally equivalent.
Co-authored-by: Gaby Baghdadi <baghdadi@ca.ibm.com>
`rename()` can be used to rename a file path via _RFIM_UNLINK. So
register it as a UV_RENAME event.
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
The file is implicitly unregistered when the change notification is
sent, only one notification is sent per registration. So we need to
re-register interest in a file after each change notification we
receive.
Co-authored-by: Gaby Baghdadi <baghdadi@ca.ibm.com>
On illumos and Solaris, fs events are implemented with
PORT_SOURCE_FILE type event ports. These are one-shot so
need re-arming each time they fire. Once they are armed
and an event occurs, the kernel removes them from the current
cache list and puts them on an event queue to be read by
the application.
There's a window in closing one of these ports when it could
have triggered and be pending delivery. In that case, the
attempt to disarm (dissociate) the event will fail with ENOENT
but libuv still goes ahead and closes down the handle. In
particular, the close callback (uv_close() argument) will be
called but then the event will subsequently be delivered if
the loop is still active; this should not happen.
This commit adds the support for a custom strtok implementation, which
is reentrant. On some systems strtok_r or strstep is available for that
purpose; however, since these are an extension, it is difficult to
control if it will be available on every supported system.
Remove the `TARGET_OS_IPHONE` ifdef to include posix spawn headers for
iOS build. Previously https://github.com/libuv/libuv/pull/3257
introduced posix spawn with \_\_APPLE\_\_ platform only, which resulted
in a number of spawn related definitions not found for iOS (such as
`uv__posix_spawn_fncs_tag`).
Co-authored-by: Jameson Nash <vtjnash@gmail.com>
Although the change remapped the error code to the correct one, a lot of
code already depends on the incorrect one, so it's not worth the
breakage.
This reverts commit 04a35efe69.
Refs: https://github.com/nodejs/node/pull/42340
Signed-off-by: Darshan Sen <raisinten@gmail.com>
Bug #3504 seems to affect more platforms than just OpenBSD. As this
seems to be a race condition in these kernels, we do not want to fail
because of it. Instead, we remove the WNOHANG flag from waitpid, and
track exactly which processes have exited. Should also be a slight speed
improvement for excessively large numbers of live children.
Now that uv__cloexec_fcntl() is simplified
(https://github.com/libuv/libuv/pull/3492), there is no benefit to
maintaining duplicate code paths for the same thing.
We can save a syscall on most modern systems (required by POSIX 2008),
but not on all systems.
Also handle errors from CLOEXEC. Even though fcntl does not really
define there to be any, it could theoretically be EBADF if the user
happened to pass a bad file descriptor to the same number fd (such that
no other code happened to already fail on that).
From user reports, it appears that OpenBSD has a broken kevent NOTE_EXIT
implementation. However, we can simply go back to the old, slower
version therefore.
Fix: https://github.com/libuv/libuv/issues/3504
Replacement for the usage pattern where people use uv_cpu_info() as an
imperfect heuristic for determining the amount of parallelism that is
available to their programs.
Fixes#3493.
Fixes: https://github.com/libuv/libuv/issues/3050
Refs: https://github.com/libuv/libuv/issues/3086
Refs: https://github.com/libuv/libuv/pull/3064
Refs: https://github.com/libuv/libuv/pull/3107
Refs: https://github.com/libuv/libuv/pull/3064
This reverts commit 217fdf4265, then fixes
several issues with it:
* remove error fast-cleanup code that triggers a nodejs bug
Refs: https://github.com/libuv/libuv/pull/3107#issuecomment-782482608
* protect posix_spawn from EINTR
This is not a documented valid error, but seems to have been observed.
* ignore setuid/setgid syscall
This kernel function is not permitted unless the process is setuid root,
so disable this syscall. Falling back to fork/exec should be okay for
the rare cases that the user decides they need to do setuid(getuid()) or
setuid(geteuid()) for the child.
Refs: https://github.com/libuv/libuv/pull/3107#issuecomment-782482608
* improve posix_spawn path search
Ports the improvements in musl back to this function
* fix some additional problems and formatting issues
We previously might fail to start a watcher, in rare failure cases,
resulting in a zombie that we would fail to kill. Also avoid creating
the signal-pipe unless required (addresses a review comment from Apple)
* fix fd->fd mapping reuse
There was a chance that when duplicating the fd's into stdio_count+fd we
might be closing a currently opened fd with that value.
The GNU/Hurd platform does not define IP_ADD_SOURCE_MEMBERSHIP,
IP_DROP_SOURCE_MEMBERSHIP, MCAST_JOIN_SOURCE_GROUP and
MCAST_LEAVE_SOURCE_GROUP.
Implement a few functions for the GNU/Hurd. Specifically:
* uv_resident_set_memory (from Linux)
* uv_get_free_memory (from Linux)
* uv_get_total_memory (from Linux)
* uv_cpu_info (from cygwin)
* uv__process_title_cleanup (void)
* uv_get_constrained_memory (stub)
* Leave proctitle unimplemented on Hurd for now
* Implement hurdish uv_exepath
* Enable ifaddrs api
* Unbreak udp basics
* Unbreak futime and lutime on Hurd
I created `uv__backend_timeout` to be used internally for this reason,
then forgot to use it, resulting in flaky tests and excessive trips
around the uv_run loop.
Fix#3472
If we try to use uv_fs_rmdir on a read-only directory on Windows, it
internally calls _wrmdir, which sets _doserrno to ERROR_ACCESS_DENIED
and errno to EACCES. However, ERROR_ACCESS_DENIED is mapped to
UV_EPERM, so I believe it should be remapped to UV_EACCES.
Currently `LoadLibraryA` call first attempts to load the given DLL from
the application working directory before loading it from the system DLL
path. This may pose a security risk if an attacker is able to place a
malicious DLL into the application working directory as that DLL will
be loaded instead of the system DLL. This is especially dangerous if
the application is running with elevated privileges.
This changes the DLL loading to use `LoadLibraryExA` method with
`LOAD_LIBRARY_SEARCH_SYSTEM32` flag which restricts the DLL load
path to system DLL path, ignoring any DLLs in the application working
directory.
Reverts 442aa1f469, since this is an
improved API in Windows Vista that is now usable as a replacement. It
simplifies the code substantially, while returning nearly the same
result (on my system, the performance counters were 6 seconds behind).
The old code also did not work on Wine-5.0 (where I observed that
`data_size == data_block->HeaderLength`, and so no data was present).
This adds a workaround for an xnu kernel bug that sometimes results in
SIGCHLD not being delivered. The workaround is to use kevent to listen
for EVFILT_PROC/NOTE_EXIT events instead of relying on SIGCHLD on *BSD.
Apple rdar: FB9529664
Refs: https://github.com/libuv/libuv/pull/3257
The process title mutex was destroyed on library unload without ensuring
it was initialized - and it may not be because it's initialized lazily.
On most platforms it worked by accident because an "all zeroes" mutex is
synonymous with an initialized and unlocked mutex, but not on NetBSD.
Refs: https://github.com/libuv/libuv/pull/3286#issuecomment-1014058782
uv_thread_create_ex() lets you set a stack size that is smaller than is
safe. It enforces a lower bound of PTHREAD_STACK_MIN (when that constant
is defined) but with musl libc that's still too small to receive signals
on.
Put the lower bound at 8192 or PTHREAD_STACK_MIN, whichever is greater.
The same restriction was already in place for the _default_ stack size.
With MUSL libc, the struct msghdr is padded to align with the types used
in the Linux kernel headers (int vs size_t). When the padding was not
zeroed, the syscall would return EMSGSIZE because the random bytes in
the padding would be read by kernel as part of the size_t type.
Fixes: https://github.com/libuv/libuv/issues/3416
Currently it's checking pointers to the uv_buf_t fields match the size
of the iovec fields. This is true on traditional architectures where
pointers are just machine word-sized integers, but not on CHERI, and
thus Arm's Morello prototype, where pointers contain additional metadata
(including bounds and permissions). Drop the & to fix this.
macOS versions 10.10 and 10.15 - and presumbaly 10.11 to 10.14, too -
have a bug where a race condition causes the kernel to return EPROTOTYPE
because the socket isn't fully constructed.
It's probably the result of the peer closing the connection and that is
why libuv translates it to ECONNRESET.
Previously, libuv retried until the EPROTOTYPE error went away but some
VPN software causes the same behavior except the error is permanent, not
transient, turning the retry mechanism into an infinite loop.
Refs: https://github.com/libuv/libuv/pull/482
Refs: https://github.com/libuv/libuv/pull/3405
It's been reported in the past that OS X 10.10, because of a race
condition in the XNU kernel, sometimes returns a transient EPROTOTYPE
error when trying to write to a socket. Libuv handles that by retrying
the operation until it succeeds or fails with a different error.
Recently it's been reported that current versions of the operating
system formerly known as OS X fail permanently with EPROTOTYPE under
certain conditions, resulting in an infinite loop.
Because Apple isn't exactly forthcoming with bug fixes or even details,
I'm opting to simply remove the workaround and have the error bubble up.
Refs: https://github.com/libuv/libuv/pull/482
On z/OS, instead of calling the uv__threadpool_cleanup() function from
inside uv_library_shutdown(), the destructor attribute must be used;
otherwise, tests will fail with exit code 1 and no output. Additionally,
post() does not need to be called when the destructor attribute is used.
Also adds uv__os390_cleanup() function to clean System V message queue
on z/OS.
Co-authored-by: Igor Todorovski <itodorov@ca.ibm.com>
Co-authored-by: Gaby Baghdadi <baghdadi@ca.ibm.com>
We observed crashes inside CFRelease in uv__get_cpu_speed on the new
Mac Book Pro (arm) hardware. The problem is that the stack got
clobbered. On the new mac hardware the returned length is 8.
For the 4 byte case, a temp variable is used to avoid having to add
endian-sensitive offsets.
Fixes: https://github.com/libuv/libuv/issues/3355
The combination EVFILT_WRITE+EV_EOF is valid and indicates that the
reader has disconnected (called `shutdown(SHUT_RD)`). Probably very rare
in practice, but this seems more correct.
Issue noticed (for UV_DISCONNECT clients of uv_poll), while doing
research for https://github.com/libuv/libuv/pull/3250.
In particular, previously the main thread would have an id of NULL,
which was then not valid to use with any other API that expected a
uv_thread_t handle.