The Errno::INPROGRESS error signals that the TCP handshake has been
signaled to the peer already, by which locally we just have wait for it
to be writable.
For simple plaintext requests, this was working correctly, because the
interest was always writable no matter what. However, when wrapped in
the SSL conn, and with the OS tcp stack under more stress, the interest
could be switched to readable, and by reuse, never reset; if, by
subsequent reconnection, EINPROGRESS would be emitted, the socket would
wait for readable instead, resulting in a loop and subsequent
connectionnn timeout.
by analyzing all of the data down to the parser, one can estimate better
whether io wants to read/write/both, thereby avoiding spurious wakeups.
This also greatly simplifies the monitor API, and solves the 100% CPU
utilization issue.
using ip tables to drop SYN packets on port 9090; this requires to run
the container in privileged mode. It was also necessary to handle the
Errno::ETIMEDOUT error, as this has to be directly transformed into a
connection error
The code from which the buffer and string handling was adapted,
inherited also the usage of slice!, which is not the appropriate tool
for when dealing with byte streams. Ruby doesn't have an equivalent
String#byteslice! yet, so we adapted other known workarounds (see
https://bugs.ruby-lang.org/issues/13626) for our code. This means that:
- For HTTPX::Buffer, we add a shift! method, as all usage shift the
buffer part which has been written to the socket;
- For HTTP1 parser and Chunker, we have to double the usage of
byteslice. In the cases where it results in nil, we might needlessly
initialize an empty string, however this is the lesser of evils, until a
proper backport is in place.
header;
this was wrongly closing connections for HTTP/1.1 connections which
didn't send a "Connection" header; according to spec, the default is
"Keep-Alive", contrary to HTTP/1.0
issued to the request host, which doesn't make sense.
This also fixed an inconsistency when passing an hash of IOs. The key of
that hash MUST match the request authority for the channel to properly
assign it.