7865 Commits

Author SHA1 Message Date
Olivier Houchard
24b8fe874e BUG/MEDIUM: stream_interface: Make sure we read all the data available.
In si_cs_recv(), when there's an error on the connection or the conn_stream,
don't give up if CS_FL_RCV_MORE is set on the conn_stream, as it means there's
still data available.
2018-11-29 17:39:04 +01:00
Olivier Houchard
3e1f68bcf9 BUG/MEDIUM: stream_interface: Don't check if the handshake is done.
In si_cs_send(), don't give up and subscribe if the connection is still
waiting for a SSL handshake. We will never be woken up once the handshake is
done if we're using HTTP/2. Instead, directly try to send data. When using
the mux_pt, if the handshake is not done yet, snd_buf() would return 0 and
we will subscribe anyway.
2018-11-29 17:39:04 +01:00
Olivier Houchard
d76bd2d40b BUG/MEDIUM: connections: Don't forget to detach the connection from the SI.
When we're deferring the mux choice until the ALPN is negociated, we
attach the connection to the stream_interface until it's done, so that we
can destroy it if something goes wrong and the stream is destroy.
Before calling si_attach_cs() to attach the conn_stream once we have it,
call si_detach_endpoint(), or is_attach_cs() would destroy the connection.
2018-11-29 17:39:04 +01:00
Olivier Houchard
70d9b2fdb0 BUG/MEDIUM: connections: Wake the stream once the mux is chosen.
When we defer the mux choice until the ALPN is negociated, don't forget
to wake the stream once it's done, or it will never have the opportunity
to send data.
2018-11-29 17:39:04 +01:00
Baptiste Assmann
6be139f867 BUG/MINOR: ssl: ssl_sock_parse_clienthello ignores session id
In ssl_sock_parse_clienthello(), the code considers that SSL Sessionid
size is '1', and then considers that the SSL cipher suite is availble
right after the session id size information.
This actually works in a single case, when the client does not send a
session id.

This patch fixes this issue by introducing the a propoer way to parse
the session id and move forward the cursor by the session id length when
required.

Need to be backported to 1.8.
2018-11-29 16:55:29 +01:00
Olivier Houchard
1ced485b29 BUG/MEDIUM: mux_pt: Don't forget to unsubscribe() on attach.
In the mux_pt, when we're attaching a new conn_stream, don't forget to
unsubscribe from the connection. Failure to do so may lead to the mux_pt
freeing the connection while the conn_stream can still want to access it.
2018-11-29 13:52:31 +01:00
Olivier Houchard
0024a98640 BUG/MEDIUM: h2: Don't bogusly error if the previous stream was closed.
In h2_process_demux(), if we're demuxing multiple frames, and the previous
frame led to a stream getting closed, don't bogusly consider that an error,
and destroy the next stream, as there are valid cases where the stream could
be closed.
2018-11-28 14:09:55 +01:00
Tim Duesterhus
3f024f3be5 CLEANUP: http: Fix typo in init_http's comment
It read "non-zero" where it should read zero.
2018-11-28 04:20:51 +01:00
William Lallemand
d913800a7d BUG/MEDIUM: listeners: CLOEXEC flag is not correctly set
The CLOEXEC flag was set using a F_SETFL which can't work.
To set the CLOEXEC flag F_SETFD should be used, the problem is that it
needs a new call to fcntl() and it's on the path of every accept.

This flag was only needed in the case of the master, so the patch was
reverted and the flag set only in this case.

The bug was introduced by 0b3e849 ("MEDIUM: listeners: set O_CLOEXEC on
the accepted FDs").

No backport needed.
2018-11-27 19:34:00 +01:00
William Lallemand
4b58c80ee2 REORG: mworker: declare master variable in global.h
This variable is used at several places, better declare it in global.h.
2018-11-27 19:34:00 +01:00
William Lallemand
c03eb01c1a BUG/MEDIUM: mworker: avoid leak of client socket
If the master was reloaded and there was a established connection to a
server, the FD resulting from the accept was leaking.

There was no CLOEXEC flag set on the FD of the socketpair created during
a connect call. This is specific to the socketpair in the master process
but it should be applied to every protocol in case we use them in the
master at some point.

No backport needed.
2018-11-27 19:34:00 +01:00
Willy Tarreau
680b2bdf2f MINOR: h2: make struct h2_ops static
There's no reason to export this descriptor, it used to be needed during
early H2 development and will complicate porting to HTX.
2018-11-27 09:59:48 +01:00
Christopher Faulet
6160832bf7 BUG/MINOR: proto_htx: only mark connections private if NTLM is detected
The commit fd9b68c48 ("BUG/MINOR: only mark connections private if NTLM is
detected") was forgotten when HTX analyzers were added.
2018-11-27 09:25:35 +01:00
Lukas Tribus
7706b85e0c MINOR: ssl: free ctx when libssl doesn't support NPN
The previous fix da95fd90 ("BUILD/MINOR: ssl: fix build with non-alpn/
non-npn libssl") does fix the build in old OpenSSL release, but I
overlooked that the ctx is only freed when NPN is supported.

Fix this by moving the #endif to the proper place (this was broken in
c7566001 ("MINOR: server: Add "alpn" and "npn" keywords")).
2018-11-27 04:32:32 +01:00
Willy Tarreau
7f0165e399 MEDIUM: memory: make the pool cache an array and not a thread_local
Having a thread_local for the pool cache is messy as we need to
initialize all elements upon startup, but we can't until the threads
are created, and once created it's too late. For this reason, the
allocation code used to check for the pool's initialization, and
it was the release code which used to detect the first call and to
initialize the cache on the fly, which is not exactly optimal.

Now that we have initcalls, let's turn this into a per-thread array.
This array is initialized very early in the boot process (STG_PREPARE)
so that pools are always safe to use. This allows to remove the tests
from the alloc/free calls.

Doing just this has removed 2.5 kB of code on all cumulated pool_alloc()
and pool_free() paths.
2018-11-26 19:50:32 +01:00
Willy Tarreau
b6b3df3ed3 MEDIUM: initcall: use initcalls for a few initialization functions
signal_init(), init_log(), init_stream(), and init_task() all used to
only preset some values and lists. This needs to be done very early to
provide a reliable interface to all other users. The calls used to be
explicit in haproxy.c:init(). Now they're placed in initcalls at the
STG_PREPARE stage. The functions are not exported anymore.
2018-11-26 19:50:32 +01:00
Willy Tarreau
2455cebe00 MEDIUM: memory: use pool_destroy_all() to destroy all pools on deinit()
Instead of exporting a number of pools and having to manually delete
them in deinit() or to have dedicated destructors to remove them, let's
simply kill all pools on deinit().

For this a new function pool_destroy_all() was introduced. As its name
implies, it destroys and frees all pools (provided they don't have any
user anymore of course).

This allowed to remove 4 implicit destructors, 2 explicit ones, and 11
individual calls to pool_destroy(). In addition it properly removes
the mux_pt_ctx pool which was not cleared on exit (no backport needed
here since it's 1.9 only). The sig_handler pool doesn't need to be
exported anymore and became static now.
2018-11-26 19:50:32 +01:00
Willy Tarreau
8ceae72d44 MEDIUM: init: use initcall for all fixed size pool creations
This commit replaces the explicit pool creation that are made in
constructors with a pool registration. Not only this simplifies the
pools declaration (it can be done on a single line after the head is
declared), but it also removes references to pools from within
constructors. The only remaining create_pool() calls are those
performed in init functions after the config is parsed, so there
is no more user of potentially uninitialized pool now.

It has been the opportunity to remove no less than 12 constructors
and 6 init functions.
2018-11-26 19:50:32 +01:00
Willy Tarreau
7107c8b494 MINOR: memory: add a callback function to create a pool
The new function create_pool_callback() takes 3 args including the
return pointer, and creates a pool with the specified name and size.
In case of allocation error, it emits an error message and returns.

The new macro REGISTER_POOL() registers a callback using this function
and will be usable to request some pools creation and guarantee that
the allocation will be checked. An even simpler approach is to use
DECLARE_POOL() and DECLARE_STATIC_POOL() which declare and register
the pool.
2018-11-26 19:50:32 +01:00
Willy Tarreau
e655251e80 MINOR: initcall: use initcalls for section parsers
The two calls to cfg_register_section() and cfg_register_postparser()
are now supported by initcalls. This allowed to remove two other
constructors.
2018-11-26 19:50:32 +01:00
Willy Tarreau
172f5ce948 MINOR: initcall: use initcalls for most post_{check,deinit} and per_thread*
Most calls to hap_register_post_check(), hap_register_post_deinit(),
hap_register_per_thread_init(), hap_register_per_thread_deinit() can
be done using initcalls and will not require a constructor anymore.
Let's create a set of simplified macros for this, called respectively
REGISTER_POST_CHECK, REGISTER_POST_DEINIT, REGISTER_PER_THREAD_INIT,
and REGISTER_PER_THREAD_DEINIT.

Some files were not modified because they wouldn't benefit from this
or because they conditionally register (e.g. the pollers).
2018-11-26 19:50:32 +01:00
Willy Tarreau
8071338c78 MINOR: initcall: apply initcall to all register_build_opts() calls
Most register_build_opts() calls use static strings. These ones were
replaced with a trivial REGISTER_BUILD_OPTS() statement adding the string
and its call to the STG_REGISTER section. A dedicated section could be
made for this if needed, but there are very few such calls for this to
be worth it. The calls made with computed strings however, like those
which retrieve OpenSSL's version or zlib's version, were moved to a
dedicated function to guarantee they are called late in the process.
For example, the SSL call probably requires that SSL_library_init()
has been called first.
2018-11-26 19:50:32 +01:00
Willy Tarreau
86abe44e42 MEDIUM: init: use self-initializing spinlocks and rwlocks
This patch replaces a number of __decl_hathread() followed by HA_SPIN_INIT
or HA_RWLOCK_INIT by the new __decl_spinlock() or __decl_rwlock() which
automatically registers the lock for initialization in during the STG_LOCK
init stage. A few static modifiers were lost in the process, but since they
were not essential at all it was not worth extending the API to provide such
a variant.
2018-11-26 19:50:32 +01:00
Willy Tarreau
a8ae77da61 MINOR: thread: provide a set of lock initialisers
This patch adds ha_spin_init() and ha_rwlock_init() which are used as
a callback to initialise locks at boot time. They perform exactly the
same as HA_SPIN_INIT() or HA_RWLOCK_INIT() but from within a real
function.
2018-11-26 19:50:32 +01:00
Willy Tarreau
0108d90c6c MEDIUM: init: convert all trivial registration calls to initcalls
This switches explicit calls to various trivial registration methods for
keywords, muxes or protocols from constructors to INITCALL1 at stage
STG_REGISTER. All these calls have in common to consume a single pointer
and return void. Doing this removes 26 constructors. The following calls
were addressed :

- acl_register_keywords
- bind_register_keywords
- cfg_register_keywords
- cli_register_kw
- flt_register_keywords
- http_req_keywords_register
- http_res_keywords_register
- protocol_register
- register_mux_proto
- sample_register_convs
- sample_register_fetches
- srv_register_keywords
- tcp_req_conn_keywords_register
- tcp_req_cont_keywords_register
- tcp_req_sess_keywords_register
- tcp_res_cont_keywords_register
- flt_register_keywords
2018-11-26 19:50:32 +01:00
Willy Tarreau
5794fb0c22 MINOR: init: process all initcalls in order at boot time
main() now iterates over all initcall stages at boot time. This will allow
to move init code from constructors to initcalls.
2018-11-26 19:50:32 +01:00
William Lallemand
7c756a8ccc BUG/MEDIUM: mworker: fix FD leak upon reload
We reintroduced some FDs leaking by using a poller and some listeners in
the master.

The master proxy needs to be stopped to avoid leaking its listeners, the
polling loop needs to be deinit, and the thread waker pipe need to be
closed too.

No backport needed.
2018-11-26 19:31:17 +01:00
Willy Tarreau
e548974ca8 MINOR: compression: always create the compression pool
Surprisingly, the compression pool was created at runtime on first use,
which is not very convenient, has performance and reliability impacts,
and even makes monitoring less easy. Let's move the pool creation at
startup time instead. This even removes the need for the spinlock in
case USE_ZLIB is not defined.
2018-11-26 14:46:55 +01:00
Willy Tarreau
3bfcd10218 BUILD: compression: fix build error with DEFAULT_MAXZLIBMEM
The tune.maxzlibmem setting was moved with commit 368780334 ("MEDIUM:
compression: move the zlib-specific stuff from global.h to compression.c")
but the preset value using DEFAULT_MAXZLIBMEM was incorrectly moved :
  - the field is in "global" and not "global.tune"
  - the trailing comma instead of semi-colon will make it either zero
    (threads enabled), break (threads enabled with debugging), or cast
    the memprintf's return pointer to int (threads disabled)

It simply proves that nobody ever used DEFAULT_MAXZLIBMEM since 1.8!

This needs to be backported to 1.8.
2018-11-26 10:27:51 +01:00
Tim Duesterhus
742e0f9f1f BUG/MINOR: mworker: Do not attempt to close(2) fd -1
Valgrind reports:

==3389== Warning: invalid file descriptor -1 in syscall close()

Check for >= 0 before closing.

This bug was introduced in commit ce83b4a5dd48c000dec68f9d551945d21e9ac7ac
and is specific to 1.9. No backport needed.
2018-11-26 08:35:41 +01:00
Lukas Tribus
da95fd901b BUILD/MINOR: ssl: fix build with non-alpn/non-npn libssl
In commit c7566001 ("MINOR: server: Add "alpn" and "npn" keywords") and
commit 201b9f4e ("MAJOR: connections: Defer mux creation for outgoing
connection if alpn is set"), the build was broken on older OpenSSL
releases.

Move the #ifdef's around so that we build again with older OpenSSL
releases (0.9.8 was tested).
2018-11-26 08:34:40 +01:00
Willy Tarreau
082f559d36 BUG/MEDIUM: h2: restart demuxing after releasing buffer space
Since the connection changes in 1.9, some breakage happened to the H2 mux
whose initial design was heavily relying on the fact that connection-level
functions were woken up after data were transferred to the stream layer.

We need to wake the demux up after receiving such data if the demux is
blocked. This at least allows to receive POSTs again. One issue remains,
it looks like the end of the uploaded data is silently discarded if the
server responds before the end of the transfer (H2 in half-closed(local)
state), which doesn't happen with 1.8.14 and nghttp as the client.

No backport is needed.
2018-11-25 09:06:42 +01:00
Willy Tarreau
1ed87b77b4 BUG/MEDIUM: h2: wake the processing task up after demuxing
After the changes to the connection layer in 1.9, some wake up calls
need to be introduced to re-activate reading from the connection. One
such place is at the end of h2_process_demux(), otherwise processing
of input data stops after a few frames.

No backport is needed.
2018-11-25 08:52:11 +01:00
Olivier Houchard
ee23b2a1e3 MEDIUM: servers: Store the connection in the SI until we have a mux.
When we create a connection, if we have to defer the conn_stream and the
mux creation until we can decide it (ie until the SSL handshake is done, and
the ALPN is decided), store the connection in the stream_interface, so that
we're sure we can destroy it if needed.
2018-11-23 19:11:14 +01:00
Olivier Houchard
25607afa0a BUG/MEDIUM: sessions: Set sess->origin to NULL if the origin was destroyed.
When ending a stream, if the origin is an appctx, the appctx will have been
destroyed already, but it does not destroy the session. So later, when we
try to destroy the session, we try to dereference sess->origin and die
trying.
Fix this by explicitely setting sess->origin to NULL before calling
session_free().
2018-11-23 14:56:46 +01:00
Olivier Houchard
1295016873 BUG/MEDIUM: servers: Don't check if we have a conn_stream too soon.
The creation of the conn_stream for an outgoing connection has been delayed
a bit, and when using dispatch, a check was made to see if a conn_stream
was attached before the conn_stream was created, so remove the test, as
it's done later anyway, and create and install the conn_stream right away
when we don't have a server, as is done when we don't have an alpn/npn
defined.
2018-11-23 14:56:21 +01:00
Olivier Houchard
c6e0bb4944 MINOR: server: Only defined conn_complete_server if USE_OPENSSL is set.
conn_complete_server() is only used when using ALPN/NPN, so only define it
if USE_OPENSSL is set.
2018-11-23 14:56:13 +01:00
Olivier Houchard
637b695d6a BUG/MEDIUM: connections: Don't reset the conn flags in *connect_server().
In the various connect_server() functions, don't reset the connection flags,
as some may have been set before. The flags are initialized in conn_init(),
anyway.
2018-11-23 14:55:18 +01:00
Olivier Houchard
7fc3be76c7 MINOR: servers: Free [idle|safe|priv]_conns on exit.
Don't forget to free idle_conns, safe_conns and priv_conns on exit.

This can be backported to 1.8.
2018-11-22 19:53:03 +01:00
Olivier Houchard
6b77f49e78 MEDIUM: ssl: Add ssl_bc_alpn and ssl_bc_npn sample fetches.
Add 2 new sample fetches, ssl_bc_alpn and ssl_bc_npn, that provides the
ALPN and the NPN for an outgoing connection.
2018-11-22 19:52:44 +01:00
Olivier Houchard
201b9f4eb5 MAJOR: connections: Defer mux creation for outgoing connection if alpn is set.
If an ALPN (or a NPN) was chosen for a server, defer choosing the mux until
after the SSL handshake is done, and the ALPN/NPN has been negociated, so
that we know which mux to pick.
2018-11-22 19:52:23 +01:00
Olivier Houchard
66b5166af9 MEDIUM: connection: Don't bother reactivating polling after connection retry.
As we now will no longer try tro subscribe to recv/send events before the
connection is established, there's no need to reactivate polling on the fd
when retrying connection. It will be activated later on subscribe.
2018-11-22 19:50:39 +01:00
Olivier Houchard
c756600103 MINOR: server: Add "alpn" and "npn" keywords.
Add new keywords to "server" lines, alpn and npn.
If set, when connecting through SSL, those alpn/npn will be negociated
during the SSL handshake.
2018-11-22 19:50:08 +01:00
Willy Tarreau
beb859abce MINOR: polling: add an option to support busy polling
In some situations, especially when dealing with low latency on processors
supporting a variable frequency or when running inside virtual machines,
each time the process waits for an I/O using the poller, the processor
goes back to sleep or is offered to another VM for a long time, and it
causes excessively high latencies.

A solution to this provided by this patch is to enable busy polling using
a global option. When busy polling is enabled, the pollers never sleep and
loop over themselves waiting for an I/O event to happen or for a timeout
to occur. On multi-processor machines it can significantly overheat the
processor but it usually results in much lower latencies.

A typical test consisting in injecting traffic over a single connection at
a time over the loopback shows a bump from 4640 to 8540 connections per
second on forwarded connections, indicating a latency reduction of 98
microseconds for each connection, and a bump from 12500 to 21250 for
locally terminated connections (redirects), indicating a reduction of
33 microseconds.

It is only usable with epoll and kqueue because select() and poll()'s
API is not convenient for such usages, and the level of performance they
are used in doesn't benefit from this anyway.

The option, which obviously remains disabled by default, can be turned
on using "busy-polling" in the global section, and turned off later
using "no busy-polling". Its status is reported in "show info" to help
troubleshooting suspicious CPU spikes.
2018-11-22 19:47:30 +01:00
Willy Tarreau
48f8bc1368 MINOR: poller: move the call of tv_update_date() back to the pollers
The reason behind this will be to be able to compute a timeout when
busy polling.
2018-11-22 18:57:37 +01:00
William Lallemand
744a08903e BUG/MINOR: mworker: fix FD leak and memory leak in error path
Fix some memory leak and a FD leak in the error path of the master proxy
initialisation. It's a really minor issue since the process is exiting
when taking those error paths.
2018-11-22 17:34:12 +01:00
Tim Duesterhus
4cae3b2f33 BUG/MINOR: cli: Fix memory leak
Valgrind's memcheck reports memory leaks in cli.c, because
the out parameter of memprintf is not properly freed:

  ==31035== 11 bytes in 1 blocks are definitely lost in loss record 16 of 101
  ==31035==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==31035==    by 0x4C2FDEF: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==31035==    by 0x4A3C72: my_realloc2 (standard.h:1364)
  ==31035==    by 0x4A3C72: memvprintf (standard.c:3459)
  ==31035==    by 0x4A3D93: memprintf (standard.c:3482)
  ==31035==    by 0x4AF77E: mworker_cli_sockpair_new (cli.c:2324)
  ==31035==    by 0x48E826: init (haproxy.c:1749)
  ==31035==    by 0x408BBC: main (haproxy.c:2725)
  ==31035==
  ==31035== 11 bytes in 1 blocks are definitely lost in loss record 17 of 101
  ==31035==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==31035==    by 0x4C2FDEF: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==31035==    by 0x4A3C72: my_realloc2 (standard.h:1364)
  ==31035==    by 0x4A3C72: memvprintf (standard.c:3459)
  ==31035==    by 0x4A3D93: memprintf (standard.c:3482)
  ==31035==    by 0x4AF071: mworker_cli_proxy_create (cli.c:2172)
  ==31035==    by 0x48EC89: init (haproxy.c:1760)
  ==31035==    by 0x408BBC: main (haproxy.c:2725)

These leaks were introduced in commits
ce83b4a5dd48c000dec68f9d551945d21e9ac7ac and
8a02257d88276e2f2f10c407d2961995f74a192c
which are specific to haproxy 1.9 dev.
2018-11-22 17:34:12 +01:00
Willy Tarreau
4f93e0c280 MINOR: cli/activity: rename the stolen CPU time fields to mention milliseconds
The "cpust_{tot,1s,15s}" fields used to report milliseconds but nothing
in the value's title made this explicit. Let's rename the field to report
"cpust_ms_{tot,1s,15s}" to more easily remind that the unit represents
milliseconds.
2018-11-22 16:13:17 +01:00
Willy Tarreau
70fe94419c MINOR: sample: add cpu_calls, cpu_ns_avg, cpu_ns_tot, lat_ns_avg, lat_ns_tot
These sample fetch keywords report performance metrics about the task calling
them. They are useful to report in logs which requests consume too much CPU
time and what negative performane impact it has on other requests. Typically
logging cpu_ns_avg and lat_ns_avg will show culprits and victims.
2018-11-22 16:07:39 +01:00
Willy Tarreau
9efd7456e0 MEDIUM: tasks: collect per-task CPU time and latency
Right now we measure for each task the cumulated time spent waiting for
the CPU and using it. The timestamp uses a 64-bit integer to report a
nanosecond-level date. This is only enabled when "profiling.tasks" is
enabled, and consumes less than 1% extra CPU on x86_64 when enabled.
The cumulated processing time and wait time are reported in "show sess".

The task's counters are also reset when an HTTP transaction is reset
since the HTTP part pretends to restart on a fresh new stream. This
will make sure we always report correct numbers for each request in
the logs.
2018-11-22 15:44:21 +01:00