Implement a best effort approach to mitigating accept() EMFILE errors.
We have a spare file descriptor stashed away that we close to get below
the EMFILE limit. Next, we accept all pending connections and close them
immediately to signal the clients that we're overloaded - and we are, but
we still keep on trucking.
There is one caveat: it's not reliable in a multi-threaded environment.
The file descriptor limit is per process. Our party trick fails if another
thread opens a file or creates a socket in the time window between us
calling close() and accept().
Fixes#315.
Don't spin in epoll_wait() / kevent() / port_getn() / etc. when we can't
accept() a new connection due to having reached the file descriptor limit.
Pass the error to the connection_cb and let the libuv user deal with it.
Some memory was leaked when the uv_udp_t handle was closed when there were
in-flight send requests with a heap allocated buffer list.
That doesn't happen much in practice. In the common case (writing < 5 buffers),
the buffer list is stored inside the uv_udp_send_t structure, not allocated on
the heap.
uv_async_send would always return 1 when non-gcc compilers were used.
When uv_async_send returns 1 no attempt is made to make port_getn
return, so in this situation uv_async_send didn't wake up the event
loop.
Set the non-blocking and close-on-exec flags with ioctl() instead of fcntl(),
it's about 10-25% faster.
Stick with fcntl() on Solaris. ioctl(FIONBIO) works but is twice as slow as
fcntl(O_NONBLOCK). ioctl(FIOCLEX) doesn't raise an error but doesn't actually
work either.
uv_update_time does not overwrite the high 32 bits of uv_loop_t.time.
It merely increments it by one when the low 32 bits have wrapped. That
means that `time` needs to be initialized to zero before
uv_update_time() is called for the first time.
Don't try the pipe2() or socketpair(O_CLOEXEC) syscalls when a previous call to
uv__make_pipe() or uv__make_socketpair() call established that the kernel
doesn't support it. Speeds up pipe and socketpair creation on older kernels.
Variables tagged with __read_mostly are put into a separate ELF section to
improve the cache locality of data that is read often but seldom written to.
kqueue(2) on osx doesn't work (emits EINVAL error) with specific fds
(i.e. /dev/tty, /dev/null, etc). When given such descriptors - start
select(2) watcher thread that will emit io events.
uv_fs_poll_t has an embedded uv_timer_t handle that got closed at a time when
the memory of the encapsulating handle might already have been deallocated.
Solve that by moving the poller's state into a structure that is allocated on
the heap and can be freed independently.