Commit Graph

5192 Commits

Author SHA1 Message Date
Thierry FOURNIER
a30b5dbf85 MINOR: lua: add AppletHTTP class and service
This class is used by Lua code for running as an applet called in HTTP mode
It defines also the associated lua service
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
f0a64b676f MINOR: lua: add AppletTCP class and service
This class is used by Lua code for running as an applet called in TCP mode.
It defines also the lua service.
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
5a363e71b2 MINOR: stream/applet: add use-service action
This new target can be called from the frontend or the backend. It
is evaluated just before the backend choice and just before the server
choice. So, the input stream or HTTP request can be forwarded to a
server or to an internal service.
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
1245a8318a MINOR: applet: add an execution timeout
This patch only declares the execution timeout variable. The applet
must be respect or ignore it. For example an applet who doing some
network accesses and doesn't control its execution yime should use
this timeout.
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
c069cfdfea MINOR: applet: add init function
this patch adds init function for the applet. the HAProxy standard
applet (peers, stats, lua) have no standard way for the applet
initialisation. This new function pointer have for goal to try to
standardize the applet initialization.
2015-09-28 01:03:48 +02:00
Thierry FOURNIER
2f3867f429 BUG/MEDIUM: lua: don't reset undesired flags in hlua_ctx_resume
Some flags like HLUA_MUST_GC must not be cleared otherwise sessions are
not properly cleaned.
2015-09-28 01:03:43 +02:00
Willy Tarreau
acc980036f MEDIUM: action: add a new flag ACT_FLAG_FIRST
This flag is used by custom actions to know that they're called for the
first time. The only case where it's not set is when they're resuming
from a yield. It will be needed to let them know when they have to
allocate some resources.
2015-09-27 23:34:39 +02:00
Thierry FOURNIER
7c39ab4ac2 OPTIM/MEDIUM: lua: executes the garbage collector only when using cosocket
The garbage collector is a little bit heavy to run, and it was added
only for cosockets. This patch prevent useless executions when no
cosockets are used.
2015-09-27 22:56:40 +02:00
Thierry FOURNIER
6ab4d8ec0e MEDIUM: lua: change the GC policy
The GC is run each times that an Lua function exit with an error or with a success.
2015-09-27 22:22:37 +02:00
Thierry FOURNIER
6d695e6314 BUG/MEDIUM: lua: socket destroy before reading pending data
When the channel is down, the applet is waked up. Before this patch,
the applet closes the stream and the unread data are discarded.

After this patch, the stream is not closed except if the buffers are
empty.

It will be closed later by the close function, or by the garbage collector.
2015-09-27 21:50:26 +02:00
Thierry FOURNIER
8c8fbbe103 MINOR: lua/applet: the cosocket applet should use appctx_wakeup in place of task_wakeup
It seems that in the new applet system, the applet me be wakeup with the
function appctx_wakeup() in place of the function task_wakeup().
2015-09-27 19:30:26 +02:00
Willy Tarreau
bb3c09ab2b CLEANUP: config: make the errorloc/errorfile messages less confusing
Some users believe that "status code XXX not handled" means "not handled
by haproxy". Let's be clear that's only about the option.
2015-09-27 15:13:30 +02:00
Thierry FOURNIER
c2f5653452 MINOR: lua: extend socket address to support non-IP families
The HAProxy Lua socket respects the Lua Socket tcp specs. these specs
are a little bit limited, it not permits to connect to unix socket.

this patch extends a little it the specs. It permit to accept a
syntax that begin with "unix@", "ipv4@", "ipv6@", "fd@" or "abns@".
2015-09-27 15:04:32 +02:00
Thierry FOURNIER
7fe3be7281 MINOR: standard: avoid DNS resolution from the function str2sa_range()
This patch blocks the DNS resolution in the function str2sa_range(),
this is useful if the function is used during the HAProxy runtime.
2015-09-27 15:04:32 +02:00
Willy Tarreau
55dcaf6521 DOC: clarify how to make use of abstract sockets in socat
Socat's abstract sockets can be made compatible with haproxy's provided
that an option is passed. It's not obvious, so let's mention it in the
doc.
2015-09-27 15:04:24 +02:00
Willy Tarreau
528192d310 MEDIUM: lua: only allow actions to yield if not in a final call
Actions may yield but must not do it during the final call from a ruleset
because it indicates there will be no more opportunity to complete or
clean up. This is indicated by ACT_FLAG_FINAL in the action's flags,
which must be passed to hlua_resume().

Thanks to this, an action called from a TCP ruleset is properly woken
up and possibly finished when the client disconnects.
2015-09-27 11:04:19 +02:00
Willy Tarreau
394586836f MEDIUM: http: pass ACT_FLAG_FINAL to custom actions
In HTTP it's more difficult to know when to pass the flag or not
because all actions are supposed to be final and there's no inspection
delay. Also, the input channel may very well be closed without this
being an error. So we only set the flag when option abortonclose is
set and the input channel is closed, which is the only case where the
user explicitly wants to forward a close down the chain.
2015-09-27 11:04:06 +02:00
Willy Tarreau
c1b10d38d7 MEDIUM: actions: add new flag ACT_FLAG_FINAL to notify about last call
This new flag indicates to a custom action that it must not yield because
it will not be called anymore. This addresses an issue introduced by commit
bc4c1ac ("MEDIUM: http/tcp: permit to resume http and tcp custom actions"),
which made it possible to yield even after the last call and causes Lua
actions not to be stopped when the session closes. Note that the Lua issue
is not fixed yet at this point. Also only TCP rules were handled, for now
HTTP rules continue to let the action yield since we don't know whether or
not it is a final call.
2015-09-27 11:04:06 +02:00
Willy Tarreau
658b85b68d MEDIUM: actions: pass a new "flags" argument to custom actions
Since commit bc4c1ac ("MEDIUM: http/tcp: permit to resume http and tcp
custom actions"), some actions may yield and be called back when new
information are available. Unfortunately some of them may continue to
yield because they simply don't know that it's the last call from the
rule set. For this reason we'll need to pass a flag to the custom
action to pass such information and possibly other at the same time.
2015-09-27 11:04:06 +02:00
Thierry FOURNIER
eba6f64a5f BUG/MEDIUM: lua: wakeup task on bad conditions
the condition was :
 * wakeup for read if the output channel contains data
 * wakeup for write if the input channel have some room.
2015-09-27 11:03:19 +02:00
Thierry FOURNIER
5a50a85f4f BUG/MEDIUM: lua: forces a garbage collection
When a thread stops this patch forces a garbage collection which
cleanup and free the memory.

The HAProxy Lua Socket class contains an HAProxy session, so it
uses a big amount of memory, in other this Socket class uses a
filedescriptor and maintain a connection open.

If the class Socket is stored in a global variable, the Socket stay
alive along of the life of the process (except if it is closed by the
other size, or if a timeout is reached). If the class Socket is stored
in a local variable, it must die with this variable.

The socket is closed by a call from the garbage collector. And the
portability and use of a variable is known by the same garbage collector.

so, running the GC just after the end of all Lua code ensure that the
heavy resources like the socket class are freed quickly.
2015-09-27 11:03:08 +02:00
Willy Tarreau
3adac08849 BUG/MEDIUM: lua: properly set the target on the connection
Not having the target set on the connection causes it to be released
at the last moment, and the destination address to randomly be valid
depending on the data found in the memory at this moment. In practice
it works as long as memory poisonning is disabled. The deep reason is
that connect_server() doesn't expect to be called with SF_ADDR_SET and
an existing connection with !reuse. This causes the release of the
connection, its reallocation (!reuse), and taking the address from the
newly allocated connection. This should certainly be improved.
2015-09-26 17:56:23 +02:00
Willy Tarreau
9af89f7905 BUG/MEDIUM: lua: better fix for the protocol check
Commit d75cb0f ("BUG/MAJOR: lua: segfault after the channel data is
modified by some Lua action.") introduced a regression causing an
action run from a TCP rule in an HTTP proxy to end in HTTP error
if it terminated cleanly, because it didn't parse the HTTP request!

Relax the test so that it takes into account the opportunity for the
analysers to parse the message.
2015-09-26 11:50:08 +02:00
Willy Tarreau
de70fa17a9 MINOR: lua: use the proper applet wakeup mechanism
The lua code must the the appropriate wakeup mechanism for cosockets.
It wakes them up from outside the stream and outside the applet, so it
shouldn't use the applet's wakeup callback which is designed only for
use from within the applet itself. For now it didn't cause any trouble
(yet).
2015-09-26 11:25:05 +02:00
Thierry FOURNIER
10e5bc76c7 BUG/MEDIUM: lua: longjmp function must be unregistered
the longjmp function must be unregistered when we leaves the function
who install it.
2015-09-26 01:34:29 +02:00
Willy Tarreau
7a4501757f CLEANUP: lua: remove unneeded memset(0) after calloc()
No need for these memset() anymore, since calloc() was put there
to avoid them.
2015-09-26 01:33:24 +02:00
Thierry FOURNIER
3c7a77c0e7 CLEANUP: lua: use calloc in place of malloc
calloc is safer because it fills the allocated memory zone with zeros.
2015-09-26 01:32:06 +02:00
Willy Tarreau
1895428ef4 DEBUG: add p_malloc() to return a poisonned memory area
This one is useful to detect improperly initialized memory areas
when some suspicious malloc() are involved in random behaviours.
2015-09-26 01:28:43 +02:00
Thierry FOURNIER
d75cb0fce6 BUG/MAJOR: lua: segfault after the channel data is modified by some Lua action.
When an action or a fetch modify the channel data, the http request parser
pointer become inconsistent. This patch detects the modification and call
again the parser.
2015-09-26 00:37:55 +02:00
Thierry FOURNIER
84e73c8882 MEDIUM: lua: use the function lua_rawset in place of lua_settable
The function lua_settable uses the metatable for acessing data,
so in the C part, we want to index value in the real table and
not throught the meta-methods. It's much faster this way.
2015-09-26 00:37:35 +02:00
Thierry FOURNIER
d2a3dcc8bd MINOR: lua: identify userdata objects
This patch adds lua primitives for identifying lua class
associated with userdata.
2015-09-25 23:40:20 +02:00
Thierry FOURNIER
a7b536b53b MINOR: lua: reset pointer after use
After releasing the Lua environment, this patch set the only one pointer to
the Lua stack to NULL. This prevents an accidental re-use.
2015-09-25 23:40:02 +02:00
Thierry FOURNIER
fd50f0bcc8 MINOR: http: split initialization
The goal is to export the http txn initialisation functions for
using it in the Lua code.
2015-09-25 23:39:48 +02:00
Thierry FOURNIER
8d16de0ad0 MINOR: http: export function http_msg_analyzer()
Exports the function http_msg_analyzer().
2015-09-25 23:39:43 +02:00
Thierry FOURNIER
127169e7f5 MINOR: http: export the get_reason() function
This patch exports the get_reason() function.
2015-09-25 23:39:36 +02:00
Thierry FOURNIER
3c3317849f MINOR: http: export http_get_path() function
This patch simply exports the http_get_path() function from the proto_http.c file.
2015-09-25 23:39:27 +02:00
Thierry FOURNIER
0efc94cbb4 CLEANUP: lua: align defines
Align the defined values
2015-09-25 23:28:02 +02:00
Thierry FOURNIER
27929fbfd7 MINOR: channel: rename function chn_sess to chn_strm
The name of the function chn_sess is no longer appropriate.
This patch renames it to chn_strm.
2015-09-25 23:27:33 +02:00
Thierry FOURNIER
ed08d6a9be MEDIUM: proto_http: smp_prefetch_http initialize txn
When we call the function smp_prefetch_http(), if the txn is not initialized,
it doesn't work. This patch fix this. Now, smp_prefecth_http() permits to use
http with any proxy mode.
2015-09-25 23:27:23 +02:00
Willy Tarreau
958f0742a2 BUG/MEDIUM: stream-int: avoid double-call to applet->release
While the SI_ST_DIS state is set *after* doing the close on a connection,
it was set *before* calling release on an applet. Applets have no internal
flags contrary to connections, so they have no way to detect they were
already released. Because of this it happened that applets were closed
twice, once via si_applet_release() and once via si_release_endpoint() at
the end of a transaction. The CLI applet could perform a double free in
this case, though the situation to cause it is quite hard because it
requires that the applet is stuck on output in states that produce very
few data.

In order to solve this, we now assign the SI_ST_DIS state *after* calling
->release, and we refrain from doing so if the state is already assigned.
This makes applets work much more like connections and definitely avoids
this double release.

In the future it might be worth making applets have their own flags like
connections to carry their own state regardless of the stream interface's
state, especially when dealing with connection reuse.

No backport is needed since this issue was caused by the rearchitecture
in 1.6.
2015-09-25 21:16:03 +02:00
Willy Tarreau
5cfa3bcc22 MINOR: cli: do not call the release handler on internal error.
It's dangerous to call this on internal state error, because it risks
to perform a double-free. This can only happen when a state is not
handled. Note that the switch/case currently doesn't offer any option
for missed states since they're all declared. Better fix this anyway.
The fix was tested by commenting out some entries in the switch/case.
2015-09-25 21:16:03 +02:00
Willy Tarreau
c9e930accc BUG/MEDIUM: cli: properly handle closed output
Due to the code inherited from the early CLI mode with the non-interactive
code, the SHUTR status was only considered while waiting for a request,
which prevents the connection from properly being closed during a dump,
and the connection used to remain established. This issue didn't happen
in 1.5 because while this part was missed, the resynchronization performed
in process_session() would detect the situation and handle the cleanup.

No backport is needed.
2015-09-25 21:16:03 +02:00
Willy Tarreau
68c00c7185 BUG/MINOR: stats: do not call cli_release_handler 3 times
If an error happens during a dump on the CLI, an explicit call to
cli_release_handler() is performed. This is not needed anymore since
we introduced ->release() in the applet which is called upon error.
Let's remove this confusing call which can even be risky in some
situations.
2015-09-25 21:16:02 +02:00
Willy Tarreau
eca572fe7f BUG/MEDIUM: applet: fix reporting of broken write situation
If an applet tries to write to a closed connection, it hangs forever.
This results in some "get map" commands on the CLI to leave orphaned
connections alive.

Now the applet wakeup function detects that the applet still wants to
write while the channel is closed for reads, which is the equivalent
to the common "broken pipe" situation. In this case, an error is
reported on the stream interface, just as it happens with connections
trying to perform a send() in a similar situation.

With this fix the stats socket is properly released.
2015-09-25 21:16:02 +02:00
Willy Tarreau
aa977ba205 MINOR: stream-int: rename si_applet_done() to si_applet_wake_cb()
This function is a callback made only for calls from the applet handler.
Rename it to remove confusion. It's currently called from the Lua code
but that's not correct, we should call the notify and update functions
instead otherwise it will not enable the applet again.
2015-09-25 21:16:02 +02:00
Willy Tarreau
335520305c MEDIUM: stream-int: completely remove stream_int_update_embedded()
This one is not needed anymore as what it used to do is either
completely covered by the new stream_int_notify() function, or undesired
and inherited from the past as a side effect of introducing the
connections.

This update is theorically never called since it's assigned only when
nothing is connected to the stream interface. However a test has been
added to si_update() to stay safe if some foreign code decides to call
si_update() in unsafe situations.
2015-09-25 21:16:02 +02:00
Willy Tarreau
651e18292d MEDIUM: stream-int: use the same stream notification function for applets and conns
The code to report completion after a connection update or an applet update
was almost the same since applets stole it from the connection. But the
differences made them hard to maintain and prevented the creation of new
functions doing only one part of the work.

This patch replaces the common code from the si_conn_wake_cb() and
si_applet_wake_cb() with a single call to stream_int_notify() which only
notifies the stream (si+channels+task) from the outside.

No functional change was made beyond this.
2015-09-25 21:16:02 +02:00
Willy Tarreau
615f28bec1 MINOR: stream-int: implement the stream_int_notify() function
stream_int_notify() was taken from the common part between si_conn_wake_cb()
and si_applet_done(). It is designed to report activity to a stream from
outside its handler. It'll generally be used by lower layers to report I/O
completion but may also be used by remote streams if the buffer processing
is shared.
2015-09-25 21:16:02 +02:00
Willy Tarreau
ea3cc48d64 MEDIUM: stream-int: clean up the conditions to enable reading in si_conn_wake_cb
The condition to release the SI_FL_WAIT_ROOM flag was abnormally
complicated because it was inherited from 6 years ago before we used
to check for the buffer's emptiness. The CF_READ_PARTIAL flag had to be
removed, and the complex test was replaced with a simpler one checking
if *some* data were moved out or not.

The reason behind this change is to have a condition compatible with
both connections and applets, as applets currently don't work very
well in this area. Specifically, some optimizations on the applet
side cause them not to release the flag above until the buffer is
empty, which may prevent applets from taking together (eg: peers
over large haproxy buffers and small kernel buffers).
2015-09-25 18:07:16 +02:00
Willy Tarreau
388a2385a5 MINOR: stream-int: move the applet_pause call out of the stream updates
It's just to split the part dealing with the stream update and the part
dealing with the applet update in si_applet_done().
2015-09-25 18:07:16 +02:00