]> git.ipfire.org Git - thirdparty/haproxy.git/log
thirdparty/haproxy.git
5 years agoMINOR: h2/trace: report the frame type when known
Willy Tarreau [Wed, 25 Sep 2019 05:28:44 +0000 (07:28 +0200)] 
MINOR: h2/trace: report the frame type when known

In state match error cases, we don't know what frame type was received
because we don't reach the frame parsers. Let's add the demuxed frame
type and flags in the trace when it's known. For this we make sure to
always reset h2c->dsi when switching back to FRAME_H. Only one location
was missing. The state transitions were not always clear (sometimes
reported before, sometimes after), these were clarified by being
reported only before switching.

5 years agoMINOR: h2/trace: indicate 'F' or 'B' to locate the side of an h2c in traces
Willy Tarreau [Wed, 25 Sep 2019 04:55:34 +0000 (06:55 +0200)] 
MINOR: h2/trace: indicate 'F' or 'B' to locate the side of an h2c in traces

It was difficult in traces showing h2-to-h2 communications to figure the
connection side solely based on the pointer. With this patch we prepend
'F' or 'B' before the state to make this more explicit:

[06|h2|4|mux_h2.c:5487] h2_rcv_buf(): entering : h2c=0x7f6acc026440(F,FRH) h2s=0x7f6acc021720(1,CLO)
[06|h2|4|mux_h2.c:5547] h2_rcv_buf(): leaving : h2c=0x7f6acc026440(F,FRH) h2s=0x7f6acc021720(1,CLO)
[06|h2|4|mux_h2.c:4040] h2_shutw(): entering : h2c=0x7f6acc026440(F,FRH) h2s=0x7f6acc021720(1,CLO)

5 years agoBUG/MEDIUM: tasklets: Make sure we're waking the target thread if it sleeps.
Olivier Houchard [Tue, 24 Sep 2019 12:55:28 +0000 (14:55 +0200)] 
BUG/MEDIUM: tasklets: Make sure we're waking the target thread if it sleeps.

Now that we can wake tasklet for other threads, make sure that if the thread
is sleeping, we wake it up, or the tasklet won't be executed until it's
done sleeping.
That also means that, before going to sleep, and after we put our bit
in sleeping_thread_mask, we have to check that nobody added a tasklet for
us, just checking for global_tasks_mask isn't enough anymore.

5 years agoBUG/MINOR: mux-fcgi: Use a literal string as format in app_log()
Christopher Faulet [Tue, 24 Sep 2019 12:30:46 +0000 (14:30 +0200)] 
BUG/MINOR: mux-fcgi: Use a literal string as format in app_log()

This avoid any crashes if stderr messages contain format specifiers.

This patch partially fixes the issue #295. No backport needed.

5 years agoCLEANUP: mux-fcgi: Remove the unused function fcgi_strm_id()
Christopher Faulet [Tue, 24 Sep 2019 12:10:59 +0000 (14:10 +0200)] 
CLEANUP: mux-fcgi: Remove the unused function fcgi_strm_id()

This patch partially fixes the issue #295.

5 years agoMINOR: task: introduce a thread-local "sched" variable for local scheduler stuff
Willy Tarreau [Tue, 24 Sep 2019 06:25:15 +0000 (08:25 +0200)] 
MINOR: task: introduce a thread-local "sched" variable for local scheduler stuff

The aim is to rassemble all scheduler information related to the current
thread. It simply points to task_per_thread[tid] without having to perform
the operation at each time. We save around 1.2 kB of code on performance
sensitive paths and increase the request rate by almost 1%.

5 years agoMINOR: task: split the tasklet vs task code in process_runnable_tasks()
Willy Tarreau [Tue, 24 Sep 2019 05:34:09 +0000 (07:34 +0200)] 
MINOR: task: split the tasklet vs task code in process_runnable_tasks()

There are a number of tests there which are enforced on tasklets while
they will never apply (various handlers, destroyed task or not, arguments,
results, ...). Instead let's have a single TASK_IS_TASKLET() test and call
the tasklet processing function directly, skipping all the rest.

It now appears visible that the only unneeded code is the update to
curr_task that is never used for tasklets, except for opportunistic
reporting in the debug handler, which can only catch si_cs_io_cb,
which in practice doesn't appear in any report so the extra cost
incurred there is pointless.

This change alone removes 700 bytes of code, mostly in
process_runnable_tasks() and increases the performance by about
1%.

5 years agoCLEANUP: task: cache the task_per_thread pointer
Willy Tarreau [Tue, 24 Sep 2019 05:19:08 +0000 (07:19 +0200)] 
CLEANUP: task: cache the task_per_thread pointer

In process_runnable_tasks() we perform a lot of dereferences to
task_per_thread[tid] but tid is thread_local and the compiler cannot
know that it doesn't change so this results in making lots of thread
local accesses and array dereferences. By just keeping a copy pointer
of this, we let the compiler optimize the code. Just doing this has
reduced process_runnable_tasks() by 124 bytes in the fast path. Doing
the same in wake_expired_tasks() results in 16 extra bytes saved.

5 years agoCLEANUP: task: remove impossible test
Willy Tarreau [Tue, 24 Sep 2019 05:02:40 +0000 (07:02 +0200)] 
CLEANUP: task: remove impossible test

In process_runnable_task(), after the task's process() function returns,
we used to check if the return is not NULL and is not a tasklet, to update
profiling measurements. This is useless since only tasks can return non-null
here. Let's remove this useless test.

5 years agoBUG/MEDIUM: checks: make sure the connection is ready before trying to recv
Willy Tarreau [Tue, 24 Sep 2019 08:43:03 +0000 (10:43 +0200)] 
BUG/MEDIUM: checks: make sure the connection is ready before trying to recv

As identified in issue #278, the backport of commit c594039225 ("BUG/MINOR:
checks: do not uselessly poll for reads before the connection is up")
introduced a regression in 2.0 when default checks are enabled (not
"option tcp-check"), but it did not affect 2.1.

What happens is that in 2.0 and earlier we have the fd cache which makes
a speculative call to the I/O functions after an attempt to connect, and
the __event_srv_chk_r() function was absolutely not designed to be called
while a connection attempt is still pending. Thus what happens is that the
test for success/failure expects the verdict to be final before waking up
the check task, and since the connection is not yet validated, it fails.
It will usually work over the loopback depending on scheduling, which is
why it doesn't fail in reg tests.

In 2.1 after the failed connect(), we subscribe to polling and usually come
back with a validated connection, so the function is not expected to be
called before it completes, except if it happens as a side effect of some
spurious wake calls, which should not have any effect on such a check.

The other check types are not impacted by this issue because they all
check for a minimum data length in the buffer, and wait for more data
until they are satisfied.

This patch fixes the issue by explicitly checking that the connection
is established before trying to read or to give a verdict. This way the
function becomes safe to call regardless of the connection status (even
if it's still totally ugly).

This fix must be backported to 2.0.

5 years agoBUG/MEDIUM: stream-int: Process connection/CS errors during synchronous sends
Christopher Faulet [Mon, 23 Sep 2019 14:11:57 +0000 (16:11 +0200)] 
BUG/MEDIUM: stream-int: Process connection/CS errors during synchronous sends

If an error occurred on the connection or the conn-stream, no syncrhonous send
is performed. If the error was not already processed and there is no more I/O,
it will never be processed and the stream will never be notified of this
error. This may block the stream until a timeout is reached or infinitly if
there is no timeout.

Concretly, this bug can be triggered time to time with h2spec, running the test
"http2/5.1.1/2".

This patch depends on the commit 328ed220a "BUG/MINOR: stream-int: Process
connection/CS errors first in si_cs_send()". Both must be backported to 2.0 and
probably to 1.9. In 1.9, the code is totally different, so this patch would have
to be adapted.

5 years agoBUG/MINOR: stream-int: Process connection/CS errors first in si_cs_send()
Christopher Faulet [Mon, 23 Sep 2019 13:57:29 +0000 (15:57 +0200)] 
BUG/MINOR: stream-int: Process connection/CS errors first in si_cs_send()

Errors on the connections or the conn-stream must always be processed in
si_cs_send(), even if the stream-interface is already subscribed on
sending. This patch does not fix any concrete bug per-se. But it is required by
the following one to handle those errors during synchronous sends.

This patch must be backported with the following one to 2.0 and probably to 1.9
too, but with caution because the code is really different.

5 years agoBUILD: makefile: work around yet another GCC fantasy (-Wstring-plus-int)
Willy Tarreau [Tue, 24 Sep 2019 07:43:34 +0000 (09:43 +0200)] 
BUILD: makefile: work around yet another GCC fantasy (-Wstring-plus-int)

According to issue #294 some gcc versions suspect that developers are
having trouble dealing with string offsets and now emit another new
childish warning when mapping indexes to characters. Instead of annoying
developers each time it happens and ask them to modify their valid code,
let's just get rid of this absurd warning.

5 years agoOPTIM: listeners: use tasklets for the multi-queue rings
Willy Tarreau [Tue, 24 Sep 2019 04:55:18 +0000 (06:55 +0200)] 
OPTIM: listeners: use tasklets for the multi-queue rings

Now that we can wake up a remote thread's tasklet, it's way more
interesting to use a tasklet than a task in the accept queue, as it
will avoid passing through all the scheduler. Just doing this increases
the accept rate by about 4%, overall recovering the slight loss
introduced by the tasklet change. In addition it makes sure that
even a heavily loaded scheduler (e.g. many very fast checks) will
not delay a connection accept.

5 years agoBUG/MEDIUM: namespace: fix fd leak in master-worker mode
Krisztián Kovács (kkovacs) [Fri, 20 Sep 2019 14:48:19 +0000 (14:48 +0000)] 
BUG/MEDIUM: namespace: fix fd leak in master-worker mode

When namespaces are used in the configuration, the respective namespace handles
are opened during config parsing and stored in an ebtree for lookup later.

Unfortunately, when the master process re-execs itself these file descriptors
were not closed, effectively leaking the fds and preventing destruction of
namespaces no longer present in the configuration.

This change fixes this issue by opening the namespace file handles as
close-on-exec, making sure that they will be closed during re-exec.

5 years agoBUG/MINOR: build: fix event ports (Solaris)
Emmanuel Hocdet [Thu, 19 Sep 2019 11:08:26 +0000 (11:08 +0000)] 
BUG/MINOR: build: fix event ports (Solaris)

Patch 6b308985 "MEDIUM: fd: do not use the FD_POLL_* flags in the
pollers anymore" break ev_evports.c build. Restore variable name
to fix it.

5 years agoBUILD: travis-ci: add PCRE2, SLZ build
Ilya Shipitsin [Thu, 19 Sep 2019 18:32:30 +0000 (23:32 +0500)] 
BUILD: travis-ci: add PCRE2, SLZ build

5 years agoTESTS: Add a stress-test for mt_lists.
Olivier Houchard [Mon, 23 Sep 2019 15:42:42 +0000 (17:42 +0200)] 
TESTS: Add a stress-test for mt_lists.

Add test-list.c, a stress-test for mt_list, to ensure there's no concurrency
issue.
The number of threads is provided on the command line, and it randomly
add, removes, or parses the list until it made MAX_ACTION actions (currently
5000000).

5 years agoMEDIUM: tasklets: Make the tasklet list a struct mt_list.
Olivier Houchard [Fri, 20 Sep 2019 15:18:35 +0000 (17:18 +0200)] 
MEDIUM: tasklets: Make the tasklet list a struct mt_list.

Change the tasklet code so that the tasklet list is now a mt_list.
That means that tasklet now do have an associated tid, for the thread it
is expected to run on, and any thread can now call tasklet_wakeup() for
that tasklet.
One can change the associated tid with tasklet_set_tid().

5 years agoMINOR: mt_lists: Give MT_LIST_ADD, MT_LIST_ADDQ and MT_LIST_DEL a return value.
Olivier Houchard [Fri, 20 Sep 2019 15:32:47 +0000 (17:32 +0200)] 
MINOR: mt_lists: Give MT_LIST_ADD, MT_LIST_ADDQ and MT_LIST_DEL a return value.

Make it so MT_LIST_ADD and MT_LIST_ADDQ return 1 if it managed to add the
item, 0 (because it was already in a list) otherwise.
Make it so MT_LIST_DEL returns 1 if it managed to remove the item from a
list, or 0 otherwise (because it was in no list).

5 years agoMINOR: mt_lists: Do nothing in MT_LIST_ADD/MT_LIST_ADDQ if already in list.
Olivier Houchard [Fri, 20 Sep 2019 12:44:22 +0000 (14:44 +0200)] 
MINOR: mt_lists: Do nothing in MT_LIST_ADD/MT_LIST_ADDQ if already in list.

Modify MT_LIST_ADD and MT_LIST_ADDQ to do nothing if the element is already
in a list.

5 years agoMEDIUM: servers: Use LIST_DEL_INIT() instead of LIST_DEL().
Olivier Houchard [Fri, 20 Sep 2019 16:08:29 +0000 (18:08 +0200)] 
MEDIUM: servers: Use LIST_DEL_INIT() instead of LIST_DEL().

In srv_add_to_idle_list(), use LIST_DEL_INIT instead of just LIST_DEL.
We're about to add the connection to a mt_list, and MT_LIST_ADD/MT_LIST_ADDQ
will be modified to make sure we're not adding the element if it's already
in a list.

5 years agoMINOR: mt_lists: Add new macroes.
Olivier Houchard [Mon, 12 Aug 2019 12:10:12 +0000 (14:10 +0200)] 
MINOR: mt_lists: Add new macroes.

Add a few new macroes to the mt_lists.
MT_LIST_LOCK_ELT()/MT_LIST_UNLOCK_ELT() helps locking/unlocking an element.
This should only be used if you know for sure nobody else will remove the
element from the list in the meanwhile.
mt_list_for_each_entry_safe() is an iterator, similar to
list_for_each_entry_safe().
It takes 5 arguments, item, list_head, member are similar to those of
the non-mt variant, tmpelt is a temporary pointer to a struct mt_list, while
tmpelt2 is a struct mt_list itself.
MT_LIST_DEL_SELF() can be used to delete an item while parsing the list with
mt_list_for_each_entry_safe(). It shouldn't be used outside, and you
shouldn't use MT_LIST_DEL() while using mt_list_for_each_entry_safe().

5 years agoMEDIUM: list: Separate "locked" list from regular list.
Olivier Houchard [Thu, 8 Aug 2019 13:47:21 +0000 (15:47 +0200)] 
MEDIUM: list: Separate "locked" list from regular list.

Instead of using the same type for regular linked lists and "autolocked"
linked lists, use a separate type, "struct mt_list", for the autolocked one,
and introduce a set of macros, similar to the LIST_* macros, with the
MT_ prefix.
When we use the same entry for both regular list and autolocked list, as
is done for the "list" field in struct connection, we know have to explicitely
cast it to struct mt_list when using MT_ macros.

5 years agoBUG/MEDIUM: check/threads: make external checks run exclusively on thread 1
Willy Tarreau [Tue, 3 Sep 2019 16:55:02 +0000 (18:55 +0200)] 
BUG/MEDIUM: check/threads: make external checks run exclusively on thread 1

See GH issues #141 for all the context. In short, registered signal
handlers are not inherited by other threads during startup, which is
normally not a problem, except that we need that the same thread as
the one doing the fork() cleans up the old process using waitpid()
once its death is reported via SIGCHLD, as happens in external checks.

The only simple solution to this at the moment is to make sure that
external checks are exclusively run on the first thread, the one
which registered the signal handlers on startup. It will be far more
than enough anyway given that external checks must not require to be
load balanced on multiple threads! A more complex solution could be
designed over the long term to let each thread deal with all signals
but it sounds overkill.

This must be backported as far as 1.8.

5 years agoBUG/MAJOR: mux-h2: Handle HEADERS frames received after a RST_STREAM frame
Christopher Faulet [Mon, 23 Sep 2019 13:28:20 +0000 (15:28 +0200)] 
BUG/MAJOR: mux-h2: Handle HEADERS frames received after a RST_STREAM frame

As stated in the RFC7540#5.1, an endpoint that receives any frame other than
PRIORITY after receiving a RST_STREAM MUST treat that as a stream error of type
STREAM_CLOSED. However, frames carrying compression state must still be
processed before being dropped to keep the HPACK decoder synchronized. This had
to be the purpose of the commit 8d9ac3ed8b ("BUG/MEDIUM: mux-h2: do not abort
HEADERS frame before decoding them"). But, the test on the frame type was
inverted.

This bug is major because desynchronizing the HPACK decoder leads to mixup
indexed headers in messages. From the time an HEADERS frame is received and
ignored for a closed stream, wrong headers may be sent to the following streams.

This patch may fix several bugs reported on github (#116, #290, #292). It must
be backported to 2.0 and 1.9.

5 years agoBUG/MINOR: mux-fcgi: Don't compare the filter name in its parsing callback
Christopher Faulet [Wed, 18 Sep 2019 09:18:33 +0000 (11:18 +0200)] 
BUG/MINOR: mux-fcgi: Don't compare the filter name in its parsing callback

The function parse_fcgi_flt() is called when the keyword "fcgi-app" is found on
a filter line. We don't need to compare it again in the function.

This patch fixes the issue #284. No backport needed.

5 years agoCLEANUP: fcgi-app: Remove useless test on fcgi_conf pointer
Christopher Faulet [Wed, 18 Sep 2019 09:16:02 +0000 (11:16 +0200)] 
CLEANUP: fcgi-app: Remove useless test on fcgi_conf pointer

fcgi_conf was already tested after allocation. No need to test it again.
This patch fixes the isssue #285.

5 years agoBUG/MINOR: mux-fcgi: Be sure to have a connection to unsubcribe
Christopher Faulet [Wed, 18 Sep 2019 09:11:46 +0000 (11:11 +0200)] 
BUG/MINOR: mux-fcgi: Be sure to have a connection to unsubcribe

When the mux is released, It must own the connection to unsubcribe.
This patch fixes the issue #283. No backport needed.

5 years agoBUG/MINOR: mux-h2: Be sure to have a connection to unsubcribe
Christopher Faulet [Wed, 18 Sep 2019 09:07:20 +0000 (11:07 +0200)] 
BUG/MINOR: mux-h2: Be sure to have a connection to unsubcribe

When the mux is released, It must own the connection to unsubcribe.
This patch must be backported to 2.0.

5 years agoBUILD: CI: install golang-1.13 when building BoringSSL
Ilya Shipitsin [Mon, 16 Sep 2019 11:13:10 +0000 (16:13 +0500)] 
BUILD: CI: install golang-1.13 when building BoringSSL

5 years agoBUG/MINOR: build: Fix compilation of mux_fcgi.c when compiled without SSL
Christopher Faulet [Tue, 17 Sep 2019 11:46:47 +0000 (13:46 +0200)] 
BUG/MINOR: build: Fix compilation of mux_fcgi.c when compiled without SSL

The function ssl_sock_is_ssl is only available when HAProxy is compile with the
SSL support.

This patch fixes the issue #279. No need to backport.

5 years agoMINOR: doc: Add documentation about the FastCGI support
Christopher Faulet [Thu, 12 Sep 2019 21:03:09 +0000 (23:03 +0200)] 
MINOR: doc: Add documentation about the FastCGI support

5 years agoMEDIUM: mux-fcgi: Add the FCGI multiplexer
Christopher Faulet [Sun, 11 Aug 2019 21:11:30 +0000 (23:11 +0200)] 
MEDIUM: mux-fcgi: Add the FCGI multiplexer

This multiplexer is only available on the backend side. It may handle
multiplexed connections if the FCGI application supports it. A FCGI application
must be configured on the backend to be used. If not redefined during the
request processing by the FCGI filter, this mux handles all mandatory
parameters.

There is a limitation on the way the requests are processed. The parameters must
be encoded into a uniq PARAMS record. It means, once encoded, all HTTP headers
and FCGI parameters must small enough to be store in a buffer. Otherwise, an
internal processing error is returned.

5 years agoMEDIUM: fcgi-app: Add FCGI application and filter
Christopher Faulet [Sun, 11 Aug 2019 21:11:03 +0000 (23:11 +0200)] 
MEDIUM: fcgi-app: Add FCGI application and filter

The FCGI application handles all the configuration parameters used to format
requests sent to an application. The configuration of an application is grouped
in a dedicated section (fcgi-app <name>) and referenced in a backend to be used
(use-fcgi-app <name>). To be valid, a FCGI application must at least define a
document root. But it is also possible to set the default index, a regex to
split the script name and the path-info from the request URI, parameters to set
or unset...  In addition, this patch also adds a FCGI filter, responsible for
all processing on a stream.

5 years agoMINOR: fcgi: Add code related to FCGI protocol
Christopher Faulet [Sun, 11 Aug 2019 21:08:53 +0000 (23:08 +0200)] 
MINOR: fcgi: Add code related to FCGI protocol

This code is independant and is only responsible to encode and decode part of
the FCGI protocol.

5 years agoMINOR: muxes/htx: Ignore pseudo header during message formatting
Christopher Faulet [Wed, 14 Aug 2019 14:32:25 +0000 (16:32 +0200)] 
MINOR: muxes/htx: Ignore pseudo header during message formatting

When an HTX message is formatted to an H1 or H2 message, pseudo-headers (with
header names starting by a colon (':')) are now ignored. In fact, for now, only
H2 messages have such headers, and the H2 mux already skips them when it creates
the HTX message. But in the futur, it may be useful to keep these headers in the
HTX message to help the message analysis or to do some processing during the
HTTP formatting. It would also be a good idea to have scopes for pseudo-headers
(:h1-, :h2-, :fcgi-...) to limit their usage to a specific mux.

5 years agoMINOR: h1-htx: Use the same function to copy message payload in all cases
Christopher Faulet [Mon, 12 Aug 2019 20:42:21 +0000 (22:42 +0200)] 
MINOR: h1-htx: Use the same function to copy message payload in all cases

This function will try to do a zero-copy transfer. Otherwise, it adds a data
block. The same is used for messages with a content-length, chunked messages and
messages with unknown body length.

5 years agoMEDIUM: mux-h1/h1-htx: move HTX convertion of H1 messages in dedicated file
Christopher Faulet [Sat, 10 Aug 2019 09:17:44 +0000 (11:17 +0200)] 
MEDIUM: mux-h1/h1-htx: move HTX convertion of H1 messages in dedicated file

To avoid code duplication in the futur mux FCGI, functions parsing H1 messages
and converting them into HTX have been moved in the file h1_htx.c. Some
specific parts remain in the mux H1. But most of the parsing is now generic.

5 years agoMINOR: http: Add function to parse value of the header Status
Christopher Faulet [Mon, 16 Sep 2019 09:37:05 +0000 (11:37 +0200)] 
MINOR: http: Add function to parse value of the header Status

It will be used by the mux FCGI to get the status a response.

5 years agoMINOR: log: Provide a function to emit a log for an application
Christopher Faulet [Sun, 11 Aug 2019 17:40:12 +0000 (19:40 +0200)] 
MINOR: log: Provide a function to emit a log for an application

Application is a generic term here. It is a modules which handle its own log
server list, with no dependency on a proxy. Such applications can now call the
function app_log() to log messages, passing a log server list and a tag as
parameters. Internally, the function __send_log() has been adapted accordingly.

5 years agoMINOR: istbuf: Add the function b_isteqi()
Christopher Faulet [Tue, 6 Aug 2019 14:55:52 +0000 (16:55 +0200)] 
MINOR: istbuf: Add the function b_isteqi()

This function compares a part of a buffer to an indirect string (ist), ignoring
the case of the characters.

5 years agoMINOR: http_fetch: Add sample fetches to get auth method/user/pass
Christopher Faulet [Fri, 2 Aug 2019 09:51:37 +0000 (11:51 +0200)] 
MINOR: http_fetch: Add sample fetches to get auth method/user/pass

Now, following sample fetches may be used to get information about
authentication:

 * http_auth_type : returns the auth method as supplied in Authorization header
 * http_auth_user : returns the auth user as supplied in Authorization header
 * http_auth_pass : returns the auth pass as supplied in Authorization header

Only Basic authentication is supported.

5 years agoMINOR: config: Support per-proxy and per-server post-check functions callbacks
Christopher Faulet [Mon, 12 Aug 2019 07:51:07 +0000 (09:51 +0200)] 
MINOR: config: Support per-proxy and per-server post-check functions callbacks

Most of times, when a keyword is added in proxy section or on the server line,
we need to have a post-parser callback to check the config validity for the
proxy or the server which uses this keyword.

It is possible to register a global post-parser callback. But all these
callbacks need to loop on the proxies and servers to do their job. It is neither
handy nor efficient. Instead, it is now possible to register per-proxy and
per-server post-check callbacks.

5 years agoMINOR: config: Support per-proxy and per-server deinit functions callbacks
Christopher Faulet [Wed, 31 Jul 2019 06:44:12 +0000 (08:44 +0200)] 
MINOR: config: Support per-proxy and per-server deinit functions callbacks

Most of times, when any allocation is done during configuration parsing because
of a new keyword in proxy section or on the server line, we must add a call in
the deinit() function to release allocated ressources. It is now possible to
register a post-deinit callback because, at this stage, the proxies and the
servers are already releases.

Now, it is possible to register deinit callbacks per-proxy or per-server. These
callbacks will be called for each proxy and server before releasing them.

5 years agoMINOR: http-ana: Remove err_state field from http_msg
Christopher Faulet [Mon, 9 Sep 2019 09:11:45 +0000 (11:11 +0200)] 
MINOR: http-ana: Remove err_state field from http_msg

This field is not used anymore. In addition, the state HTTP_MSG_ERROR is now
only used when an error occurred during the body forward.

5 years agoMINOR: http-ana: Handle HTX errors first during message analysis
Christopher Faulet [Mon, 9 Sep 2019 08:15:21 +0000 (10:15 +0200)] 
MINOR: http-ana: Handle HTX errors first during message analysis

When an error occurred in a mux, most of time, an error is also reported on the
conn-stream, leading to an error (read and/or write) on the channel. When a
parsing or a processing error is reported for the HTX message, it is better to
handle it first.

5 years agoMINOR: mux-h1: Report a processing error during output processing
Christopher Faulet [Mon, 9 Sep 2019 08:11:30 +0000 (10:11 +0200)] 
MINOR: mux-h1: Report a processing error during output processing

During output processing, It is unexpected to have a malformed HTX
message. Instead of reporting a parsing error, we now report a processing error.

5 years agoMINOR: htx: Add a flag on HTX message to report processing errors
Christopher Faulet [Fri, 6 Sep 2019 17:08:27 +0000 (19:08 +0200)] 
MINOR: htx: Add a flag on HTX message to report processing errors

This new flag may be used to report unexpected error because of not well
formatted HTX messages (not related to a parsing error) or our incapactity to
handle the processing because we reach a limit (ressource exhaustion, too big
headers...). It should result to an error 500 returned to the client when
applicable.

5 years agoBUILD: CI: temporarily disable ASAN
Ilya Shipitsin [Sat, 14 Sep 2019 16:18:49 +0000 (21:18 +0500)] 
BUILD: CI: temporarily disable ASAN

it turned out that ASAN breaks things. until this is resolved,
let us disable ASAN

5 years agoBUG/MEDIUM: stick-table: Properly handle "show table" with a data type argument
Christopher Faulet [Fri, 13 Sep 2019 13:15:56 +0000 (15:15 +0200)] 
BUG/MEDIUM: stick-table: Properly handle "show table" with a data type argument

Since the commit 1b8e68e8 ("MEDIUM: stick-table: Stop handling stick-tables as
proxies."), the target field into the table context of the CLI applet was not
anymore a pointer to a proxy. It was replaced by a pointer to a stktable. But,
some parts of the code was not updated accordingly. the function
table_prepare_data_request() still tries to cast it to a pointer to a proxy. The
result is totally undefined. With a bit of luck, when the "show table" command
is used with a data type, we failed to find a table and the error "Data type not
stored in this table" is returned. But crashes may also be experienced.

This patch fixes the issue #262. It must be backported to 2.0.

5 years agoBUG/MINOR: Missing stat_field_names (since f21d17bb)
Adis Nezirovic [Fri, 13 Sep 2019 09:43:03 +0000 (11:43 +0200)] 
BUG/MINOR: Missing stat_field_names (since f21d17bb)

Recently Lua code which uses Proxy class (get_stats method) stopped
working ("table index is nil from [C] method 'get_stats'")
It probably affects other codepaths too.

This should be backported do 2.0 and 1.9.

5 years agoBUG/MINOR: backend: Fix a possible null pointer dereference
Christopher Faulet [Fri, 13 Sep 2019 08:01:36 +0000 (10:01 +0200)] 
BUG/MINOR: backend: Fix a possible null pointer dereference

In the function connect_server(), when we are not able to reuse a connection and
too many FDs are opened, the variable srv must be defined to kill an idle
connection.

This patch fixes the issue #257. It must be backported to 2.0

5 years agoBUG/MINOR: acl: Fix memory leaks when an ACL expression is parsed
Christopher Faulet [Fri, 13 Sep 2019 07:50:15 +0000 (09:50 +0200)] 
BUG/MINOR: acl: Fix memory leaks when an ACL expression is parsed

This only happens during the configuration parsing. First leak is the string
representing the last converter parsed, if any. The second one is on the error
path, when the allocation of the ACL expression failed. In this case, the sample
was not released.

This patch fixes the issue #256. It must be backported to all stable versions.

5 years agoCLEANUP: mux-h2: Remove unused flag H2_SF_DATA_CHNK
Christopher Faulet [Fri, 13 Sep 2019 07:37:21 +0000 (09:37 +0200)] 
CLEANUP: mux-h2: Remove unused flag H2_SF_DATA_CHNK

Since the legacy HTTP mode has been removed, this flag is not necessary
anymore. Removing this flag, a test on the HTX message at the end of the
function h2c_decode_headers() has also been removed fixing the github
issue #244.

No backport needed.

5 years agoMINOR: sample: Add UUID-fetch
Luca Schimweg [Tue, 10 Sep 2019 13:42:52 +0000 (15:42 +0200)] 
MINOR: sample: Add UUID-fetch

Adds the fetch uuid(int). It returns a UUID following the format of
version 4 in the RFC4122 standard.

New feature, but could be backported.

5 years agoBUG/MINOR: filters: Properly set the HTTP status code on analysis error
Christopher Faulet [Fri, 6 Sep 2019 13:24:55 +0000 (15:24 +0200)] 
BUG/MINOR: filters: Properly set the HTTP status code on analysis error

When a filter returns an error during the HTTP analysis, an error must be
returned if the status code is not already set. On the request path, an error
400 is returned. On the response path, an error 502 is returned. The status is
considered as unset if its value is not strictly positive.

If needed, this patch may be backported to all versions having filters (as far
as 1.7). Because nobody have never report any bug, the backport to 2.0 is
probably enough.

5 years agoMINOR: stats: Add JSON export from the stats page
Christopher Faulet [Mon, 9 Sep 2019 13:50:54 +0000 (15:50 +0200)] 
MINOR: stats: Add JSON export from the stats page

It is now possible to export stats using the JSON format from the HTTP stats
page. Like for the CSV export, to export stats in JSON, you must add the option
";json" on the stats URL. It is also possible to dump the JSON schema with the
option ";json-schema". Corresponding Links have been added on the HTML page.

This patch fixes the issue #263.

5 years agoBUG/MINOR: ssl: always check for ssl connection before getting its XPRT context
Christopher Faulet [Tue, 10 Sep 2019 08:12:03 +0000 (10:12 +0200)] 
BUG/MINOR: ssl: always check for ssl connection before getting its XPRT context

In several SSL functions, the XPRT context is retrieved before any check on the
connection. In the function ssl_sock_is_ssl(), a test suggests the connection
may be null. So, it is safer to test the ssl connection before retrieving its
XPRT context. It removes any ambiguities and prevents possible null pointer
dereferences.

This patch fixes the issue #265. It must be backported to 2.0.

5 years agoBUG/MINOR: listener: Fix a possible null pointer dereference
Christopher Faulet [Tue, 10 Sep 2019 08:01:26 +0000 (10:01 +0200)] 
BUG/MINOR: listener: Fix a possible null pointer dereference

It seems to be possible to have no frontend for a listener. A test was missing
before dereferencing it at the end of the function listener_accept().

This patch fixes the issue #264. It must be backported to 2.0 and 1.9.

5 years agoBUILD/MINOR: auth: enabling for osx
David Carlier [Sun, 1 Sep 2019 13:59:10 +0000 (14:59 +0100)] 
BUILD/MINOR: auth: enabling for osx

macOS supports this but as part of libc.
Little typo fix while here.

5 years agoBUILD: CI: skip reg-tests/connection/proxy_protocol_random_fail.vtc on CentOS 6
Ilya Shipitsin [Fri, 6 Sep 2019 18:18:14 +0000 (23:18 +0500)] 
BUILD: CI: skip reg-tests/connection/proxy_protocol_random_fail.vtc on CentOS 6

This test relies on ALPN which is not available in CentOS 6.

5 years agoMINOR: stats: report the number of idle connections for each server
Willy Tarreau [Sun, 8 Sep 2019 07:24:56 +0000 (09:24 +0200)] 
MINOR: stats: report the number of idle connections for each server

This adds two extra fields to the stats, one for the current number of idle
connections and one for the configured limit. A tooltip link now appears on
the HTML page to show these values in front of the active connection values.

This should be backported to 2.0 and 1.9 as it's the only way to monitor
the idle connections behaviour.

5 years agoBUG/MEDIUM: connection: don't keep more idle connections than ever needed
Willy Tarreau [Sun, 8 Sep 2019 05:38:23 +0000 (07:38 +0200)] 
BUG/MEDIUM: connection: don't keep more idle connections than ever needed

When using "http-reuse safe", which is the default, a new incoming connection
does not automatically reuse an existing connection for the first request, as
we don't want to risk to lose the contents if we know the client will not be
able to replay the request. A side effect to this is that when dealing with
mostly http-close traffic, the reuse rate is extremely low and we keep
accumulating server-side connections that may even never be reused. At some
point we're limited to a ratio of file descriptors, but when the system is
configured with very high FD limits, we can still reach the limit of outgoing
source ports and make the system significantly slow down trying to find an
available port for outgoing connections. A simple test on my laptop with
ulimit 100000 and with the following config results in the load immediately
dropping after a few seconds :

   listen l1
        bind :4445
        mode http
        server s1 127.0.0.1:8000

As can be seen, the load falls from 38k cps to 400 cps during the first 200ms
(in fact when the source port table is full and connect() takes ages to find
a spare port for a new connection):

   $ injectl464 -p 4 -o 1 -u 10 -G 127.0.0.1:4445/ -F -c -w 100
   hits ^hits hits/s  ^h/s     bytes  kB/s  last  errs  tout htime  sdht ptime
   2439  2439  39338 39338    356094  5743  5743     0     0 0.4 0.5 0.4
   7637  5198  38185 37666   1115002  5575  5499     0     0 0.7 0.5 0.7
   7719    82  25730   820   1127002  3756   120     0     0 21.8 18.8 21.8
   7797    78  19492   780   1138446  2846   114     0     0 61.4 2.5 61.4
   7877    80  15754   800   1150182  2300   117     0     0 58.6 0.5 58.6
   7920    43  13200   430   1156488  1927    63     0     0 58.9 0.3 58.9

At this point, lots of connections are indeed in use, for only 10 connections
on the frontend side:

   $ ss -ant state established | wc -l
   39022

This patch makes sure we never keep more idle connections than we've ever
had outstanding requests on a server. This way the total number of idle
connections will never exceed the sum of maximum connections. Thus highly
loaded servers will be able to get many connections and slightly loaded
servers will keep less. Ideally we should apply similar limits per process
and the per backend, but in practice this already addresses the issues
pretty well:

   $ injectl464 -p 4 -o 1 -u 10 -G 127.0.0.1:4445/ -F -c -w 100
   hits ^hits hits/s  ^h/s     bytes  kB/s  last  errs  tout htime  sdht ptime
   4423  4423  40209 40209    645758  5870  5870     0     0 0.2 0.4 0.2
   8020  3597  40100 39966   1170920  5854  5835     0     0 0.2 0.4 0.2
  12037  4017  40123 40170   1757402  5858  5864     0     0 0.2 0.4 0.2
  16069  4032  40172 40320   2346074  5865  5886     0     0 0.2 0.4 0.2
  20047  3978  40013 39386   2926862  5842  5750     0     0 0.3 0.4 0.3
  24005  3958  40008 39979   3504730  5841  5837     0     0 0.2 0.4 0.2

   $ ss -ant state established | wc -l
   234

This patch must be backported to 2.0. It could be useful in 1.9 as well
eventhough pools and reuse are not enabled by default there.

5 years agoMEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore
Willy Tarreau [Fri, 6 Sep 2019 17:05:50 +0000 (19:05 +0200)] 
MEDIUM: fd: do not use the FD_POLL_* flags in the pollers anymore

As mentioned in previous commit, these flags do not map well to
modern poller capabilities. Let's use the FD_EV_*_{R,W} flags instead.
This first patch only performs a 1-to-1 mapping making sure that the
previously reported flags are still reported identically while using
the closest possible semantics in the pollers.

It's worth noting that kqueue will now support improvements such as
returning distinctions between shut and errors on each direction,
though this is not exploited for now.

5 years agoMINOR: fd: add two flags ERR and SHUT to describe FD states
Willy Tarreau [Fri, 6 Sep 2019 16:27:02 +0000 (18:27 +0200)] 
MINOR: fd: add two flags ERR and SHUT to describe FD states

There's currently a big ambiguity on our use of POLLHUP because we
currently map POLLHUP and POLLRDHUP to FD_POLL_HUP. The first one
indicates a close in *both* directions while the second one indicates
a unidirectional close. Since we don't know from the resulting flag
we always have to read when reported. Furthermore kqueue only reports
unidirectional responses which are mapped to FD_POLL_HUP as well, and
their write closes are mapped to a general error.

We could add a new FD_POLL_RDHUP flag to improve the mapping, or
switch only to the POLL* flags, but that further complicates the
portability for operating systems like FreeBSD which do not have
POLLRDHUP but have its semantics.

Let's instead directly use the per-direction flag values we already
have, and it will be a first step in the direction of finer states.
Thus we introduce an ERR and a SHUT status for each direction, that
the pollers will be able to compute and pass to fd_update_events().

It's worth noting that FD_EV_STATUS already sees the two new flags,
but they are harmless since used only by fd_{recv,send}_state() which
are never called. Thus in its current state this patch must be totally
transparent.

5 years agoMEDIUM: connection: enable reading only once the connection is confirmed
Willy Tarreau [Thu, 5 Sep 2019 15:05:05 +0000 (17:05 +0200)] 
MEDIUM: connection: enable reading only once the connection is confirmed

In order to address the absurd polling sequence described in issue #253,
let's make sure we disable receiving on a connection until it's established.
Previously with bottom-top I/Os, we were almost certain that a connection
was ready when the first I/O was confirmed. Now we can enter various
functions, including process_stream(), which will attempt to read
something, will fail, and will then subscribe. But we don't want them
to try to receive if we know the connection didn't complete. The first
prerequisite for this is to mark the connection as not ready for receiving
until it's validated. But we don't want to mark it as not ready for sending
because we know that attempting I/Os later is extremely likely to work
without polling.

Once the connection is confirmed we re-enable recv readiness. In order
for this event to be taken into account, the call to tcp_connect_probe()
was moved earlier, between the attempt to send() and the attempt to recv().
This way if tcp_connect_probe() enables reading, we have a chance to
immediately fall back to this and read the possibly pending data.

Now the trace looks like the following. It's far from being perfect
but we've already saved one recvfrom() and one epollctl():

 epoll_wait(3, [], 200, 0) = 0
 socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 7
 fcntl(7, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
 setsockopt(7, SOL_TCP, TCP_NODELAY, [1], 4) = 0
 connect(7, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
 epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN|EPOLLOUT|EPOLLRDHUP, {u32=7, u64=7}}) = 0
 epoll_wait(3, [{EPOLLOUT, {u32=7, u64=7}}], 200, 1000) = 1
 connect(7, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
 getsockopt(7, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 sendto(7, "OPTIONS / HTTP/1.0\r\n\r\n", 22, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 22
 epoll_ctl(3, EPOLL_CTL_MOD, 7, {EPOLLIN|EPOLLRDHUP, {u32=7, u64=7}}) = 0
 epoll_wait(3, [{EPOLLIN|EPOLLRDHUP, {u32=7, u64=7}}], 200, 1000) = 1
 getsockopt(7, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 getsockopt(7, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
 recvfrom(7, "HTTP/1.0 200\r\nContent-length: 0\r\nX-req: size=22, time=0 ms\r\nX-rsp: id=dummy, code=200, cache=1, size=0, time=0 ms (0 real)\r\n\r\n", 16384, 0, NULL, NULL) = 126
 close(7)                = 0

5 years agoMINOR: fd: add two new calls fd_cond_{recv,send}()
Willy Tarreau [Thu, 5 Sep 2019 14:39:21 +0000 (16:39 +0200)] 
MINOR: fd: add two new calls fd_cond_{recv,send}()

These two functions are used to enable recv/send but only if the FD is
not marked as active yet. The purpose is to conditionally mark them as
tentatively usable without interfering with the polling if polling was
already enabled, when it's supposed to be likely true.

5 years agoMEDIUM: fd: mark the FD as ready when it's inserted
Willy Tarreau [Thu, 5 Sep 2019 14:30:39 +0000 (16:30 +0200)] 
MEDIUM: fd: mark the FD as ready when it's inserted

Given that all our I/Os are now directed from top to bottom and not the
opposite way around, and the FD cache was removed, it doesn't make sense
anymore to create FDs that are marked not ready since this would prevent
the first accesses unless the caller explicitly does an fd_may_recv()
which is not expected to be its job (which conn_ctrl_init() has to do
by the way). Let's move this into fd_insert() instead, and have a single
atomic operation for both directions via fd_may_both().

5 years agoBUG/MAJOR: ssl: ssl_sock was not fully initialized.
Emeric Brun [Fri, 6 Sep 2019 13:36:02 +0000 (15:36 +0200)] 
BUG/MAJOR: ssl: ssl_sock was not fully initialized.

'ssl_sock' wasn't fully initialized so a new session can inherit some
flags from an old one.

This causes some fetches, related to client's certificate presence or
its verify status and errors, returning erroneous values.

This issue could generate other unexpected behaviors because a new
session could also inherit other flags such as SSL_SOCK_ST_FL_16K_WBFSIZE,
SSL_SOCK_SEND_UNLIMITED, or SSL_SOCK_RECV_HEARTBEAT from an old session.

This must be backported to 2.0 but it's useless for previous.

5 years agoBUG/MINOR: lb/leastconn: ignore the server weights for empty servers
Willy Tarreau [Fri, 6 Sep 2019 15:04:04 +0000 (17:04 +0200)] 
BUG/MINOR: lb/leastconn: ignore the server weights for empty servers

As discussed in issue #178, the change brought around 1.9-dev11 by commit
1eb6c55808 ("MINOR: lb: make the leastconn algorithm more accurate")
causes some harm in the situation it tried to improve. By always applying
the server's weight even for no connection, we end up always picking the
same servers for the first connections, so under a low load, if servers
only have either 0 or 1 connections, in practice the same servers will
always be picked.

This patch partially restores the original behaviour but still keeping
the spirit of the aforementioned patch. Now what is done is that servers
with no connections will always be picked first, regardless of their
weight, so they will effectively follow round-robin. Only servers with
one connection or more will see an accurate weight applied.

This patch was developed and tested by @malsumis and @jaroslawr who
reported the initial issue. It should be backported to 2.0 and 1.9.

5 years agoMINOR: contrib/prometheus-exporter: Report DRAIN/MAINT/NOLB status for servers
Christopher Faulet [Fri, 6 Sep 2019 14:10:19 +0000 (16:10 +0200)] 
MINOR: contrib/prometheus-exporter: Report DRAIN/MAINT/NOLB status for servers

Now, following status are reported for servers:0=DOWN, 1=UP, 2=MAINT, 3=DRAIN,
4=NOLB.

It is linked to the github issue #255. Thanks to Mickaël Martin. If needed, this
patch may be backported to 2.0.

5 years agoBUILD: CI: add basic CentOS 6 cirrus build
Ilya Shipitsin [Sun, 1 Sep 2019 19:03:10 +0000 (00:03 +0500)] 
BUILD: CI: add basic CentOS 6 cirrus build

5 years agoBUG/MINOR: mux-h1: Fix a UAF in cfg_h1_headers_case_adjust_postparser()
Christopher Faulet [Tue, 30 Jul 2019 14:51:42 +0000 (16:51 +0200)] 
BUG/MINOR: mux-h1: Fix a UAF in cfg_h1_headers_case_adjust_postparser()

When an error occurs in the post-parser callback which checks configuration
validity of the option outgoing-headers-case-adjust-file, the error message is
freed too early, before being used.

No backport needed. It fixes the github issue #258.

5 years agoBUG/MINOR: checks: do not uselessly poll for reads before the connection is up
Willy Tarreau [Thu, 5 Sep 2019 15:38:40 +0000 (17:38 +0200)] 
BUG/MINOR: checks: do not uselessly poll for reads before the connection is up

It's pointless to start to perform a recv() call on a connection that is
not yet established. The only purpose used to be to subscribe but that
causes many extra syscalls when we know we can do it later.

This patch only attempts a read if the connection is established or if
there is no write planed, since we want to be certain to be called. And
in wake_srv_chk() we continue to attempt to read if the reader was not
subscribed, so as to perform the first read attempt. In case a first
result is provided, __event_srv_chk_r() will not do anything anyway so
this is totally harmless in this case.

This fix requires that commit "BUG/MINOR: checks: make __event_chk_srv_r()
report success before closing" is applied before, otherwise it will break
some checks (notably SSL) by doing them again after the connection is shut
down. This completes the fixes on the checks described in issue #253 by
roughly cutting the number of syscalls in half. It must be backported to
2.0.

5 years agoBUG/MINOR: checks: make __event_chk_srv_r() report success before closing
Willy Tarreau [Thu, 5 Sep 2019 16:43:22 +0000 (18:43 +0200)] 
BUG/MINOR: checks: make __event_chk_srv_r() report success before closing

On a plain TCP check, this function will do nothing except shutting the
connection down and will not even update the status. This prevents it
from being called again, which is the reason why we attempt to do it
once too early. Let's first fix this function to make it report success
on plain TCP checks before closing, as it does for all other ones.

This must be backported to 2.0. It should be safe to backport to older
versions but it doesn't seem it would fix anything there.

5 years agoBUG/MINOR: checks: start sending the request right after connect()
Willy Tarreau [Thu, 5 Sep 2019 15:51:30 +0000 (17:51 +0200)] 
BUG/MINOR: checks: start sending the request right after connect()

Since the change of I/O direction, we must not wait for an empty connect
callback before sending the request, we must attempt to send it as soon
as possible so that we don't uselessly poll. This is what this patch
does. This reduces the total check duration by a complete poll loop
compared to what is described in issue #253.

This must be backported to 2.0.

5 years agoBUG/MINOR: checks: stop polling for write when we have nothing left to send
Willy Tarreau [Thu, 5 Sep 2019 16:24:46 +0000 (18:24 +0200)] 
BUG/MINOR: checks: stop polling for write when we have nothing left to send

Since the change of I/O direction, we perform the connect() call and
the send() call together from the top. But the send call must at least
disable polling for writes once it does not have anything left to send.

This bug is partially responsible for the waste of resources described
in issue #253.

This must be backported to 2.0.

5 years agoCONTRIB: debug: add new program "poll" to test poll() events
Willy Tarreau [Thu, 5 Sep 2019 07:18:47 +0000 (09:18 +0200)] 
CONTRIB: debug: add new program "poll" to test poll() events

This simple program prepares a TCP connection between two ends and
allows to perform various operations on them such as send, recv, poll,
shutdown, close, reset, etc. It takes care of remaining particularly
silent to help inspection via strace, though it can also be verbose
and report status, errno, and poll events. It delays acceptation of
the incoming server-side connection so that it's even possible to
test the poll status on a listener with a pending connection, or
to close the connection without accepting it and inspect the effect
on the client.

Actions are executed in the command line order as they are parsed,
they may be grouped using commas when they are performed on the same
socket.

Example showing a successful recv() of pending data before a pending error:
   $ ./poll -v -l pol,acc,pol -c snd,shw -s pol,rcv,pol,rcv,pol,snd,lin,clo -c pol,rcv,pol,rcv,pol

   #### BEGIN ####
   cmd #1 stp #1: do_pol(3): ret=1 ev=0x1 (IN)
   cmd #1 stp #2: do_acc(3): ret=5
   cmd #1 stp #3: do_pol(3): ret=0 ev=0
   cmd #2 stp #1: do_snd(4): ret=3
   cmd #2 stp #2: do_shw(4): ret=0
   cmd #3 stp #1: do_pol(5): ret=1 ev=0x2005 (IN OUT RDHUP)
   cmd #3 stp #2: do_rcv(5): ret=3
   cmd #3 stp #3: do_pol(5): ret=1 ev=0x2005 (IN OUT RDHUP)
   cmd #3 stp #4: do_rcv(5): ret=0
   cmd #3 stp #5: do_pol(5): ret=1 ev=0x2005 (IN OUT RDHUP)
   cmd #3 stp #6: do_snd(5): ret=3
   cmd #3 stp #7: do_lin(5): ret=0
   cmd #3 stp #8: do_clo(5): ret=0
   cmd #4 stp #1: do_pol(4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP)
   cmd #4 stp #2: do_rcv(4): ret=3
   cmd #4 stp #3: do_pol(4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP)
   cmd #4 stp #4: do_rcv(4): ret=-1 (Connection reset by peer)
   cmd #4 stp #5: do_pol(4): ret=1 ev=0x2015 (IN OUT HUP RDHUP)
   #### END ####

5 years agoMINOR: fd: make updt_fd_polling() a normal function
Willy Tarreau [Wed, 4 Sep 2019 11:25:41 +0000 (13:25 +0200)] 
MINOR: fd: make updt_fd_polling() a normal function

It's called from many places, better use a real function than an inline.

5 years agoMEDIUM: fd: simplify the fd_*_{recv,send} functions using BTS/BTR
Willy Tarreau [Wed, 4 Sep 2019 11:22:50 +0000 (13:22 +0200)] 
MEDIUM: fd: simplify the fd_*_{recv,send} functions using BTS/BTR

Now that we don't have to update FD_EV_POLLED_* at the same time as
FD_EV_ACTIVE_*, we don't need to use a CAS anymore, a bit-test-and-set
operation is enough. Doing so reduces the code size by a bit more than
1 kB. One function was special, fd_done_recv(), whose comments and doc
were inaccurate for the part related to the lack of polling.

5 years agoMEDIUM: fd: remove the FD_EV_POLLED status bit
Willy Tarreau [Wed, 4 Sep 2019 07:52:57 +0000 (09:52 +0200)] 
MEDIUM: fd: remove the FD_EV_POLLED status bit

Since commit 7ac0e35f2 in 1.9-dev1 ("MAJOR: fd: compute the new fd polling
state out of the fd lock") we've started to update the FD POLLED bit a
bit more aggressively. Lately with the removal of the FD cache, this bit
is always equal to the ACTIVE bit. There's no point continuing to watch
it and update it anymore, all it does is create confusion and complicate
the code. One interesting side effect is that it now becomes visible that
all fd_*_{send,recv}() operations systematically call updt_fd_polling(),
except fd_cant_recv()/fd_cant_send() which never saw it change.

5 years agoBUG/MINOR: mux-h1: Fix a possible null pointer dereference in h1_subscribe()
Christopher Faulet [Wed, 4 Sep 2019 08:22:34 +0000 (10:22 +0200)] 
BUG/MINOR: mux-h1: Fix a possible null pointer dereference in h1_subscribe()

This patch fixes the github issue #243. No backport needed.

5 years agoBUG/MEDIUM: cache: Don't cache objects if the size of headers is too big
Christopher Faulet [Tue, 3 Sep 2019 20:22:12 +0000 (22:22 +0200)] 
BUG/MEDIUM: cache: Don't cache objects if the size of headers is too big

HTTP responses with headers than impinge upon the reserve must not be
cached. Otherwise, there is no warranty to have enough space to add the header
"Age" when such cached responses are delivered.

This patch must be backported to 2.0 and 1.9. For these versions, the same must
be done for the legacy HTTP mode.

5 years agoBUG/MEDIUM: cache: Properly copy headers splitted on several shctx blocks
Christopher Faulet [Tue, 3 Sep 2019 20:11:52 +0000 (22:11 +0200)] 
BUG/MEDIUM: cache: Properly copy headers splitted on several shctx blocks

In the cache, huge HTTP headers will use several shctx blocks. When a response
is returned from the cache, these headers must be properly copied in the
corresponding HTX message by updating the pointer where to copied a header
part.

This patch must be backported to 2.0 and 1.9.

5 years agoBUG/MINOR: mux-h1: Be sure to update the count before adding EOM after trailers
Christopher Faulet [Tue, 3 Sep 2019 19:55:14 +0000 (21:55 +0200)] 
BUG/MINOR: mux-h1: Be sure to update the count before adding EOM after trailers

Otherwise, an EOM may be added in a full buffer.

This patch must be backported to 2.0.

5 years agoBUG/MINOR: mux-h1: Don't stop anymore input processing when the max is reached
Christopher Faulet [Tue, 3 Sep 2019 14:26:15 +0000 (16:26 +0200)] 
BUG/MINOR: mux-h1: Don't stop anymore input processing when the max is reached

The loop is now stopped only when nothing else is consumed from the input buffer
or if a parsing error is encountered. This will let a chance to detect cases
when we fail to add the EOM.

For instance, when the max is reached after the headers parsing and all the
message is received. In this case, we may have the flag H1S_F_REOS set without
the flag H1S_F_APPEND_EOM and no pending input data, leading to an error because
we think it is an abort.

This patch must be backported to 2.0. This bug does not affect 1.9.

5 years agoBUG/MINOR: mux-h1: Fix size evaluation of HTX messages after headers parsing
Christopher Faulet [Tue, 3 Sep 2019 14:16:50 +0000 (16:16 +0200)] 
BUG/MINOR: mux-h1: Fix size evaluation of HTX messages after headers parsing

The block size of the start-line was not counted.

This patch must be backported to 2.0.

5 years agoBUG/MINOR: h1: Properly reset h1m when parsing is restarted
Christopher Faulet [Tue, 3 Sep 2019 14:05:31 +0000 (16:05 +0200)] 
BUG/MINOR: h1: Properly reset h1m when parsing is restarted

Otherwise some processing may be performed twice. For instance, if the header
"Content-Length" is parsed on the first pass, when the parsing is restarted, we
skip it because we think another header with the same value was already seen. In
fact, it is currently the only existing bug that can be encountered. But it is
safer to reset all the h1m on restart to avoid any future bugs.

This patch must be backported to 2.0 and 1.9

5 years agoBUG/MINOR: http-ana: Reset response flags when 1xx messages are handled
Christopher Faulet [Tue, 3 Sep 2019 13:23:54 +0000 (15:23 +0200)] 
BUG/MINOR: http-ana: Reset response flags when 1xx messages are handled

Otherwise, the following final response could inherit of some of these
flags. For instance, because informational responses have no body, the flag
HTTP_MSGF_BODYLESS is set for 1xx messages. If it is not reset, this flag will
be kept for the final response.

One of visible effect of this bug concerns the HTTP compression. When the final
response is preceded by an 1xx message, the compression is not performed. This
was reported in github issue #229.

This patch must be backported to 2.0 and 1.9. Note that the file http_ana.c does
not exist for these branches, the patch must be applied on proto_htx.c instead.

5 years agoBUILD: connection: silence gcc warning with extra parentheses
Jerome Magnin [Mon, 2 Sep 2019 07:53:41 +0000 (09:53 +0200)] 
BUILD: connection: silence gcc warning with extra parentheses

Commit 8a4ffa0a ("MINOR: send-proxy-v2: sends authority TLV according
to TLV received") is missing parentheses around a variable assignment
used as condition in an if statement, and gcc isn't happy about it.

5 years agoBUG/MEDIUM: peers: local peer socket not bound.
Frédéric Lécaille [Mon, 2 Sep 2019 12:02:28 +0000 (14:02 +0200)] 
BUG/MEDIUM: peers: local peer socket not bound.

This bug came with 015e4d7 commit: "MINOR: stick-tables: Add peers process
binding computing" where the "stick" rules cases were missing when computing
the peer local listener process binding. At parsing time we store in the
stick-table struct ->proxies_list the proxies which refer to this stick-table.
The process binding is computed after having parsed the entire configuration file
with this simple loop in cfgparse.c:

     /* compute the required process bindings for the peers from <stktables_list>
      * for all the stick-tables, the ones coming with "peers" sections included.
      */
     for (t = stktables_list; t; t = t->next) {
             struct proxy *p;

             for (p = t->proxies_list; p; p = p->next_stkt_ref) {
                     if (t->peers.p && t->peers.p->peers_fe) {
                             t->peers.p->peers_fe->bind_proc |= p->bind_proc;
                     }
             }
     }

Note that if this process binding is not correctly initialized, the child forked
by the master-worker stops the peer local listener. Should be also the case
when daemonizing haproxy.

Must be backported to 2.0.

5 years agoMINOR: build: add linux-glibc-legacy build TARGET
Lukas Tribus [Sun, 1 Sep 2019 14:48:36 +0000 (16:48 +0200)] 
MINOR: build: add linux-glibc-legacy build TARGET

As discussed in issue #128, introduce a new build TARGET
linux-glibc-legacy to allow the build on old, legacy OS.

Should be backported to 2.0.

5 years agoMINOR: send-proxy-v2: sends authority TLV according to TLV received
Emmanuel Hocdet [Thu, 29 Aug 2019 09:54:51 +0000 (11:54 +0200)] 
MINOR: send-proxy-v2: sends authority TLV according to TLV received

Since patch "7185b789", the authority TLV in a PROXYv2 header from a
client connection is stored. Authority TLV sends in PROXYv2 should be
taken into account to allow chaining PROXYv2 without droping it.

5 years agoMEDIUM: log: add support for logging to a ring buffer
Willy Tarreau [Fri, 30 Aug 2019 13:24:59 +0000 (15:24 +0200)] 
MEDIUM: log: add support for logging to a ring buffer

Now by prefixing a log server with "ring@<name>" it's possible to send
the logs to a ring buffer. One nice thing is that it allows multiple
sessions to consult the logs in real time in parallel over the CLI, and
without requiring file system access. At the moment, ring0 is created as
a default sink for tracing purposes and is available. No option is
provided to create new rings though this is trivial to add to the global
section.

5 years agoMINOR: log: add a target type instead of hacking the address family
Willy Tarreau [Fri, 30 Aug 2019 12:18:44 +0000 (14:18 +0200)] 
MINOR: log: add a target type instead of hacking the address family

Instead of detecting an AF_UNSPEC address family for a log server and
to deduce a file descriptor, let's create a target type field and
explicitly mention that the socket is of type FD.

5 years agoMEDIUM: log: use the new generic fd_write_frag_line() function
Willy Tarreau [Fri, 30 Aug 2019 12:05:35 +0000 (14:05 +0200)] 
MEDIUM: log: use the new generic fd_write_frag_line() function

When logging to a file descriptor, we'd rather use the unified
fd_write_frag_line() which uses the FD's lock than perform the
writev() ourselves and use a per-server lock, because if several
loggers point to the same output (e.g. stdout) they are still
not locked and their logs may interleave. The function above
instead relies on the fd's lock so this is safer and will even
protect against concurrent accesses from other areas (e.g traces).
The function also deals with the FD's non-blocking mode so we do
not have to keep specific code for this anymore in the logs.

5 years agoMINOR: fd/log/sink: make the non-blocking initialization depend on the initialized bit
Willy Tarreau [Fri, 30 Aug 2019 12:41:47 +0000 (14:41 +0200)] 
MINOR: fd/log/sink: make the non-blocking initialization depend on the initialized bit

Logs and sinks were resorting to dirty hacks to initialize an FD to
non-blocking mode. Now we have a bit for this in the fd tab so we can
do it on the fly on first use of the file descriptor. Previously it was
set per log server by writing value 1 to the port, or during a sink
initialization regardless of the usage of the fd.

5 years agoMINOR: fd: add a new "initialized" bit in the fdtab struct
Willy Tarreau [Fri, 30 Aug 2019 12:36:10 +0000 (14:36 +0200)] 
MINOR: fd: add a new "initialized" bit in the fdtab struct

The purpose is to be able to remember that initialization was already
done for a file descriptor. This will allow to get rid of some dirty
hacks performed in the logs or fd sinks where the init state of the
fd has to be guessed.

5 years agoCLEANUP: fd: remove leftovers of the fdcache
Willy Tarreau [Fri, 30 Aug 2019 12:33:11 +0000 (14:33 +0200)] 
CLEANUP: fd: remove leftovers of the fdcache

The "cache" entry was still present in the fdtab struct and it was
reported in "show sess". Removing it broke the cache-line alignment
on 64-bit machines which is important for threads, so it was fixed
by adding an attribute(aligned()) when threads are in use. Doing it
only in this case allows 32-bit thread-less platforms to see the
struct fit into 32 bytes.