haproxy: Update all patches for HAProxy v1.8.8
authorChristian Lachner <gladiac@gmail.com>
Thu, 10 May 2018 18:37:15 +0000 (20:37 +0200)
committerChristian Lachner <gladiac@gmail.com>
Thu, 10 May 2018 18:37:15 +0000 (20:37 +0200)
- Add new patches (see https://www.haproxy.org/bugs/bugs-1.8.8.html)
- Raise patch-level to 03

Signed-off-by: Christian Lachner <gladiac@gmail.com>
net/haproxy/Makefile
net/haproxy/patches/0007-BUG-MINOR-config-disable-http-reuse-on-TCP-proxies.patch [new file with mode: 0644]
net/haproxy/patches/0008-BUG-MINOR-checks-Fix-check--health-computation-for-flapping-servers.patch [new file with mode: 0644]
net/haproxy/patches/0009-BUG-MEDIUM-threads-Fix-the-sync-point-for-more-than-32-threads.patch [new file with mode: 0644]
net/haproxy/patches/0010-BUG-MINOR-lua-Put-tasks-to-sleep-when-waiting-for-data.patch [new file with mode: 0644]
net/haproxy/patches/0011-DOC-MINOR-clean-up-LUA-documentation-re-servers-array-table.patch [new file with mode: 0644]
net/haproxy/patches/0012-BUG-MINOR-map-correctly-track-reference-to-the-last-ref_elt-being-dumped.patch [new file with mode: 0644]
net/haproxy/patches/0013-BUG-MEDIUM-task-Dont-free-a-task-that-is-about-to-be-run.patch [new file with mode: 0644]
net/haproxy/patches/0014-BUG-MINOR-lua-schedule-socket-task-upon-lua-connect.patch [new file with mode: 0644]

index 44544c97fb74f5d282d0379a011b8860d492349a..61ab5a5452be92469501a02a9363d379852d1f87 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=haproxy
 PKG_VERSION:=1.8.8
-PKG_RELEASE:=02
+PKG_RELEASE:=03
 
 PKG_SOURCE:=haproxy-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=https://www.haproxy.org/download/1.8/src/
diff --git a/net/haproxy/patches/0007-BUG-MINOR-config-disable-http-reuse-on-TCP-proxies.patch b/net/haproxy/patches/0007-BUG-MINOR-config-disable-http-reuse-on-TCP-proxies.patch
new file mode 100644 (file)
index 0000000..fdca4ea
--- /dev/null
@@ -0,0 +1,31 @@
+commit 80e179128cfd78d95cdebf7195fd21299e7931b6
+Author: Willy Tarreau <w@1wt.eu>
+Date:   Sat Apr 28 07:18:15 2018 +0200
+
+    BUG/MINOR: config: disable http-reuse on TCP proxies
+    
+    Louis Chanouha reported an inappropriate warning when http-reuse is
+    present in a defaults section while a TCP proxy accidently inherits
+    it and finds a conflict with other options like the use of the PROXY
+    protocol. To fix this patch removes the http-reuse option for TCP
+    proxies.
+    
+    This fix needs to be backported to 1.8, 1.7 and possibly 1.6.
+    
+    (cherry picked from commit 46deab6e64bfda7211b7c3199ad01f136141c86f)
+    Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
+
+diff --git a/src/cfgparse.c b/src/cfgparse.c
+index 5a460381..63d2de58 100644
+--- a/src/cfgparse.c
++++ b/src/cfgparse.c
+@@ -8702,6 +8702,9 @@ out_uri_auth_compat:
+                       }
+ #endif
++                      if ((curproxy->mode != PR_MODE_HTTP) && (curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR)
++                              curproxy->options &= ~PR_O_REUSE_MASK;
++
+                       if ((curproxy->options & PR_O_REUSE_MASK) != PR_O_REUSE_NEVR) {
+                               if ((curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CLI ||
+                                   (curproxy->conn_src.opts & CO_SRC_TPROXY_MASK) == CO_SRC_TPROXY_CIP ||
diff --git a/net/haproxy/patches/0008-BUG-MINOR-checks-Fix-check--health-computation-for-flapping-servers.patch b/net/haproxy/patches/0008-BUG-MINOR-checks-Fix-check--health-computation-for-flapping-servers.patch
new file mode 100644 (file)
index 0000000..d2dd8d8
--- /dev/null
@@ -0,0 +1,42 @@
+commit edb5a1efd22eb9918574d962640cd2ae3bb45ad3
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Wed May 2 12:12:45 2018 +0200
+
+    BUG/MINOR: checks: Fix check->health computation for flapping servers
+    
+    This patch fixes an old bug introduced in the commit 7b1d47ce ("MAJOR: checks:
+    move health checks changes to set_server_check_status()"). When a DOWN server is
+    flapping, everytime a check succeds, check->health is incremented. But when a
+    check fails, it is decremented only when it is higher than the rise value. So if
+    only one check succeds for a DOWN server, check->health will remain set to 1 for
+    all subsequent failing checks.
+    
+    So, at first glance, it seems not that terrible because the server remains
+    DOWN. But it is reported in the transitional state "DOWN server, going up". And
+    it will remain in this state until it is UP again. And there is also an
+    insidious side effect. If a DOWN server is flapping time to time, It will end to
+    be considered UP after a uniq successful check, , regardless the rise threshold,
+    because check->health will be increased slowly and never decreased.
+    
+    To fix the bug, we just need to reset check->health to 0 when a check fails for
+    a DOWN server. To do so, we just need to relax the condition to handle a failure
+    in the function set_server_check_status.
+    
+    This patch must be backported to haproxy 1.5 and newer.
+    
+    (cherry picked from commit b119a79fc336f2b6074de1c3113b1682c717985c)
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/src/checks.c b/src/checks.c
+index 80a9c70d..d07a82f8 100644
+--- a/src/checks.c
++++ b/src/checks.c
+@@ -243,7 +243,7 @@ static void set_server_check_status(struct check *check, short status, const cha
+                */
+               if ((!(check->state & CHK_ST_AGENT) ||
+                   (check->status >= HCHK_STATUS_L57DATA)) &&
+-                  (check->health >= check->rise)) {
++                  (check->health > 0)) {
+                       HA_ATOMIC_ADD(&s->counters.failed_checks, 1);
+                       report = 1;
+                       check->health--;
diff --git a/net/haproxy/patches/0009-BUG-MEDIUM-threads-Fix-the-sync-point-for-more-than-32-threads.patch b/net/haproxy/patches/0009-BUG-MEDIUM-threads-Fix-the-sync-point-for-more-than-32-threads.patch
new file mode 100644 (file)
index 0000000..7574b69
--- /dev/null
@@ -0,0 +1,48 @@
+commit 830324444e57c042666b17ac4584352cca85dafd
+Author: Christopher Faulet <cfaulet@haproxy.com>
+Date:   Wed May 2 16:58:40 2018 +0200
+
+    BUG/MEDIUM: threads: Fix the sync point for more than 32 threads
+    
+    In the sync point, to know if a thread has requested a synchronization, we call
+    the function thread_need_sync(). It should return 1 if yes, otherwise it should
+    return 0. It is intended to return a signed integer.
+    
+    But internally, instead of returning 0 or 1, it returns 0 or tid_bit
+    (threads_want_sync & tid_bit). So, tid_bit is casted in integer. For the first
+    32 threads, it's ok, because we always check if thread_need_sync() returns
+    something else than 0. But this is a problem if HAProxy is started with more
+    than 32 threads, because for threads 33 to 64 (so for tid 32 to 63), their
+    tid_bit casted to integer are evaluated to 0. So the sync point does not work for
+    more than 32 threads.
+    
+    Now, the function thread_need_sync() respects its contract, returning 0 or
+    1. the function thread_no_sync() has also been updated to avoid any ambiguities.
+    
+    This patch must be backported in HAProxy 1.8.
+    
+    (cherry picked from commit 148b16e1ceb819dfcef4c45828121d9cd7474b35)
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/src/hathreads.c b/src/hathreads.c
+index daf226ce..944a0d5b 100644
+--- a/src/hathreads.c
++++ b/src/hathreads.c
+@@ -85,7 +85,7 @@ void thread_want_sync()
+ /* Returns 1 if no thread has requested a sync. Otherwise, it returns 0. */
+ int thread_no_sync()
+ {
+-      return (threads_want_sync == 0);
++      return (threads_want_sync == 0UL);
+ }
+ /* Returns 1 if the current thread has requested a sync. Otherwise, it returns
+@@ -93,7 +93,7 @@ int thread_no_sync()
+  */
+ int thread_need_sync()
+ {
+-      return (threads_want_sync & tid_bit);
++      return ((threads_want_sync & tid_bit) != 0UL);
+ }
+ /* Thread barrier. Synchronizes all threads at the barrier referenced by
diff --git a/net/haproxy/patches/0010-BUG-MINOR-lua-Put-tasks-to-sleep-when-waiting-for-data.patch b/net/haproxy/patches/0010-BUG-MINOR-lua-Put-tasks-to-sleep-when-waiting-for-data.patch
new file mode 100644 (file)
index 0000000..3b298f9
--- /dev/null
@@ -0,0 +1,31 @@
+commit 335bc7b74eee84f0a3bcb615cadd23fe01d1336c
+Author: PiBa-NL <PiBa.NL.dev@gmail.com>
+Date:   Wed May 2 22:27:14 2018 +0200
+
+    BUG/MINOR: lua: Put tasks to sleep when waiting for data
+    
+    If a lua socket is waiting for data it currently spins at 100% cpu usage.
+    This because the TICK_ETERNITY returned by the socket is ignored when
+    setting the 'expire' time of the task.
+    
+    Fixed by removing the check for yields that return TICK_ETERNITY.
+    
+    This should be backported to at least 1.8.
+    
+    (cherry picked from commit fe971b35aeca9994f3823112c783aa796e74075a)
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/src/hlua.c b/src/hlua.c
+index bd0b87e3..0100e7cf 100644
+--- a/src/hlua.c
++++ b/src/hlua.c
+@@ -5536,8 +5536,7 @@ static struct task *hlua_process_task(struct task *task)
+       case HLUA_E_AGAIN: /* co process or timeout wake me later. */
+               notification_gc(&hlua->com);
+-              if (hlua->wake_time != TICK_ETERNITY)
+-                      task->expire = hlua->wake_time;
++              task->expire = hlua->wake_time;
+               break;
+       /* finished with error. */
diff --git a/net/haproxy/patches/0011-DOC-MINOR-clean-up-LUA-documentation-re-servers-array-table.patch b/net/haproxy/patches/0011-DOC-MINOR-clean-up-LUA-documentation-re-servers-array-table.patch
new file mode 100644 (file)
index 0000000..7f210e5
--- /dev/null
@@ -0,0 +1,252 @@
+commit 016feef5483397491af3242162934d9e9dbc6263
+Author: Patrick Hemmer <haproxy@stormcloud9.net>
+Date:   Tue May 1 21:30:41 2018 -0400
+
+    DOC/MINOR: clean up LUA documentation re: servers & array/table.
+    
+    * A few typos
+    * Fix definitions of values which are tables, not arrays.
+    * Consistent US English naming for "server" instead of "serveur".
+    
+    [tfo: should be backported to 1.6 and higher]
+    
+    (cherry picked from commit c6a1d711a4d47d68611aa28adecdadba96221bde)
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst
+index e7aa425d..2d210945 100644
+--- a/doc/lua-api/index.rst
++++ b/doc/lua-api/index.rst
+@@ -169,9 +169,9 @@ Core class
+   **context**: task, action, sample-fetch, converter
+-  This attribute is an array of declared proxies (frontend and backends). Each
+-  proxy give an access to his list of listeners and servers. Each entry is of
+-  type :ref:`proxy_class`
++  This attribute is a table of declared proxies (frontend and backends). Each
++  proxy give an access to his list of listeners and servers. The table is
++  indexed by proxy name, and each entry is of type :ref:`proxy_class`.
+   Warning, if you are declared frontend and backend with the same name, only one
+   of these are listed.
+@@ -183,12 +183,9 @@ Core class
+   **context**: task, action, sample-fetch, converter
+-  This attribute is an array of declared proxies with backend capability. Each
+-  proxy give an access to his list of listeners and servers. Each entry is of
+-  type :ref:`proxy_class`
+-
+-  Warning, if you are declared frontend and backend with the same name, only one
+-  of these are listed.
++  This attribute is a table of declared proxies with backend capability. Each
++  proxy give an access to his list of listeners and servers. The table is
++  indexed by the backend name, and each entry is of type :ref:`proxy_class`.
+   :see: :js:attr:`core.proxies`
+   :see: :js:attr:`core.frontends`
+@@ -197,12 +194,9 @@ Core class
+   **context**: task, action, sample-fetch, converter
+-  This attribute is an array of declared proxies with frontend capability. Each
+-  proxy give an access to his list of listeners and servers. Each entry is of
+-  type :ref:`proxy_class`
+-
+-  Warning, if you are declared frontend and backend with the same name, only one
+-  of these are listed.
++  This attribute is a table of declared proxies with frontend capability. Each
++  proxy give an access to his list of listeners and servers. The table is
++  indexed by the frontend name, and each entry is of type :ref:`proxy_class`.
+   :see: :js:attr:`core.proxies`
+   :see: :js:attr:`core.backends`
+@@ -336,7 +330,7 @@ Core class
+   Lua execution or resume, so two consecutive call to the function "now" will
+   probably returns the same result.
+-  :returns: an array which contains two entries "sec" and "usec". "sec"
++  :returns: a table which contains two entries "sec" and "usec". "sec"
+     contains the current at the epoch format, and "usec" contains the
+     current microseconds.
+@@ -439,9 +433,12 @@ Core class
+   **context**: body, init, task, action, sample-fetch, converter
+-  proxies is an array containing the list of all proxies declared in the
+-  configuration file. Each entry of the proxies array is an object of type
+-  :ref:`proxy_class`
++  proxies is a table containing the list of all proxies declared in the
++  configuration file. The table is indexed by the proxy name, and each entry
++  of the proxies table is an object of type :ref:`proxy_class`.
++
++  Warning, if you have declared a frontend and backend with the same name, only
++  one of these are listed.
+ .. js:function:: core.register_action(name, actions, func [, nb_args])
+@@ -852,13 +849,14 @@ Proxy class
+ .. js:attribute:: Proxy.servers
+-  Contain an array with the attached servers. Each server entry is an object of
+-  type :ref:`server_class`.
++  Contain a table with the attached servers. The table is indexed by server
++  name, and each server entry is an object of type :ref:`server_class`.
+ .. js:attribute:: Proxy.listeners
+-  Contain an array with the attached listeners. Each listeners entry is an
+-  object of type :ref:`listener_class`.
++  Contain a table with the attached listeners. The table is indexed by listener
++  name, and each each listeners entry is an object of type
++  :ref:`listener_class`.
+ .. js:function:: Proxy.pause(px)
+@@ -908,21 +906,25 @@ Proxy class
+ .. js:function:: Proxy.get_stats(px)
+-  Returns an array containg the proxy statistics. The statistics returned are
++  Returns a table containg the proxy statistics. The statistics returned are
+   not the same if the proxy is frontend or a backend.
+   :param class_proxy px: A :ref:`proxy_class` which indicates the manipulated
+     proxy.
+-  :returns: a key/value array containing stats
++  :returns: a key/value table containing stats
+ .. _server_class:
+ Server class
+ ============
++.. js:class:: Server
++
++  This class provides a way for manipulating servers and retrieving information.
++
+ .. js:function:: Server.is_draining(sv)
+-  Return true if the server is currently draining stiky connections.
++  Return true if the server is currently draining sticky connections.
+   :param class_server sv: A :ref:`server_class` which indicates the manipulated
+     server.
+@@ -930,7 +932,7 @@ Server class
+ .. js:function:: Server.set_weight(sv, weight)
+-  Dynamically change the weight of the serveur. See the management socket
++  Dynamically change the weight of the server. See the management socket
+   documentation for more information about the format of the string.
+   :param class_server sv: A :ref:`server_class` which indicates the manipulated
+@@ -939,7 +941,7 @@ Server class
+ .. js:function:: Server.get_weight(sv)
+-  This function returns an integer representing the serveur weight.
++  This function returns an integer representing the server weight.
+   :param class_server sv: A :ref:`server_class` which indicates the manipulated
+     server.
+@@ -947,16 +949,16 @@ Server class
+ .. js:function:: Server.set_addr(sv, addr)
+-  Dynamically change the address of the serveur. See the management socket
++  Dynamically change the address of the server. See the management socket
+   documentation for more information about the format of the string.
+   :param class_server sv: A :ref:`server_class` which indicates the manipulated
+     server.
+-  :param string weight: A string describing the server address.
++  :param string addr: A string describing the server address.
+ .. js:function:: Server.get_addr(sv)
+-  Returns a string describing the address of the serveur.
++  Returns a string describing the address of the server.
+   :param class_server sv: A :ref:`server_class` which indicates the manipulated
+     server.
+@@ -968,7 +970,7 @@ Server class
+   :param class_server sv: A :ref:`server_class` which indicates the manipulated
+     server.
+-  :returns: a key/value array containing stats
++  :returns: a key/value table containing stats
+ .. js:function:: Server.shut_sess(sv)
+@@ -1085,7 +1087,7 @@ Listener class
+   :param class_listener ls: A :ref:`listener_class` which indicates the
+     manipulated listener.
+-  :returns: a key/value array containing stats
++  :returns: a key/value table containing stats
+ .. _concat_class:
+@@ -1169,7 +1171,7 @@ Fetches class
+   usage. they are the chapters 7.3.2 to 7.3.6.
+   **warning** some sample fetches are not available in some context. These
+-  limitations are specified in this documentation when theire useful.
++  limitations are specified in this documentation when they're useful.
+   :see: :js:attr:`TXN.f`
+   :see: :js:attr:`TXN.sf`
+@@ -1345,13 +1347,13 @@ HTTP class
+ .. js:function:: HTTP.req_get_headers(http)
+-  Returns an array containing all the request headers.
++  Returns a table containing all the request headers.
+   :param class_http http: The related http object.
+-  :returns: array of headers.
++  :returns: table of headers.
+   :see: :js:func:`HTTP.res_get_headers`
+-  This is the form of the returned array:
++  This is the form of the returned table:
+ .. code-block:: lua
+@@ -1366,13 +1368,13 @@ HTTP class
+ .. js:function:: HTTP.res_get_headers(http)
+-  Returns an array containing all the response headers.
++  Returns a table containing all the response headers.
+   :param class_http http: The related http object.
+-  :returns: array of headers.
++  :returns: table of headers.
+   :see: :js:func:`HTTP.req_get_headers`
+-  This is the form of the returned array:
++  This is the form of the returned table:
+ .. code-block:: lua
+@@ -2210,12 +2212,12 @@ AppletHTTP class
+ .. js:attribute:: AppletHTTP.headers
+-  :returns: array
++  :returns: table
+-  The attribute headers returns an array containing the HTTP
++  The attribute headers returns a table containing the HTTP
+   headers. The header names are always in lower case. As the header name can be
+   encountered more than once in each request, the value is indexed with 0 as
+-  first index value. The array have this form:
++  first index value. The table have this form:
+ .. code-block:: lua
diff --git a/net/haproxy/patches/0012-BUG-MINOR-map-correctly-track-reference-to-the-last-ref_elt-being-dumped.patch b/net/haproxy/patches/0012-BUG-MINOR-map-correctly-track-reference-to-the-last-ref_elt-being-dumped.patch
new file mode 100644 (file)
index 0000000..af58e5f
--- /dev/null
@@ -0,0 +1,31 @@
+commit b2219ae216a141acdf0e2a3f67d2c85aee2a2bc2
+Author: Dragan Dosen <ddosen@haproxy.com>
+Date:   Fri May 4 16:27:15 2018 +0200
+
+    BUG/MINOR: map: correctly track reference to the last ref_elt being dumped
+    
+    The bug was introduced in the commit 8d85aa4 ("BUG/MAJOR: map: fix
+    segfault during 'show map/acl' on cli").
+    
+    This patch should be backported to 1.8, 1.7 and 1.6.
+    
+    (cherry picked from commit 336a11f75571ad46f74a7c6247c13ed44f95da93)
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/src/map.c b/src/map.c
+index f40e4394..a9a1e53c 100644
+--- a/src/map.c
++++ b/src/map.c
+@@ -307,9 +307,9 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
+                * reference to the last ref_elt being dumped.
+                */
+               if (appctx->st2 == STAT_ST_LIST) {
+-                      if (!LIST_ISEMPTY(&appctx->ctx.sess.bref.users)) {
+-                              LIST_DEL(&appctx->ctx.sess.bref.users);
+-                              LIST_INIT(&appctx->ctx.sess.bref.users);
++                      if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users)) {
++                              LIST_DEL(&appctx->ctx.map.bref.users);
++                              LIST_INIT(&appctx->ctx.map.bref.users);
+                       }
+               }
+               return 1;
diff --git a/net/haproxy/patches/0013-BUG-MEDIUM-task-Dont-free-a-task-that-is-about-to-be-run.patch b/net/haproxy/patches/0013-BUG-MEDIUM-task-Dont-free-a-task-that-is-about-to-be-run.patch
new file mode 100644 (file)
index 0000000..e802c7f
--- /dev/null
@@ -0,0 +1,128 @@
+commit a0f0db361978154474d76028183647d5991f3b5c
+Author: Olivier Houchard <ohouchard@haproxy.com>
+Date:   Fri May 4 15:46:16 2018 +0200
+
+    BUG/MEDIUM: task: Don't free a task that is about to be run.
+    
+    While running a task, we may try to delete and free a task that is about to
+    be run, because it's part of the local tasks list, or because rq_next points
+    to it.
+    So flag any task that is in the local tasks list to be deleted, instead of
+    run, by setting t->process to NULL, and re-make rq_next a global,
+    thread-local variable, that is modified if we attempt to delete that task.
+    
+    Many thanks to PiBa-NL for reporting this and analysing the problem.
+    
+    This should be backported to 1.8.
+    
+    (cherry picked from commit 9b36cb4a414c22e13d344afbbe70684e9f2f1d49)
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/include/proto/task.h b/include/proto/task.h
+index cbc1a907..c1c4c07e 100644
+--- a/include/proto/task.h
++++ b/include/proto/task.h
+@@ -90,6 +90,8 @@ extern unsigned int nb_tasks_cur;
+ extern unsigned int niced_tasks;  /* number of niced tasks in the run queue */
+ extern struct pool_head *pool_head_task;
+ extern struct pool_head *pool_head_notification;
++extern THREAD_LOCAL struct task *curr_task; /* task currently running or NULL */
++extern THREAD_LOCAL struct eb32sc_node *rq_next; /* Next task to be potentially run */
+ __decl_hathreads(extern HA_SPINLOCK_T rq_lock);  /* spin lock related to run queue */
+ __decl_hathreads(extern HA_SPINLOCK_T wq_lock);  /* spin lock related to wait queue */
+@@ -177,8 +179,11 @@ static inline struct task *__task_unlink_rq(struct task *t)
+ static inline struct task *task_unlink_rq(struct task *t)
+ {
+       HA_SPIN_LOCK(TASK_RQ_LOCK, &rq_lock);
+-      if (likely(task_in_rq(t)))
++      if (likely(task_in_rq(t))) {
++              if (&t->rq == rq_next)
++                      rq_next = eb32sc_next(rq_next, tid_bit);
+               __task_unlink_rq(t);
++      }
+       HA_SPIN_UNLOCK(TASK_RQ_LOCK, &rq_lock);
+       return t;
+ }
+@@ -230,7 +235,7 @@ static inline struct task *task_new(unsigned long thread_mask)
+  * Free a task. Its context must have been freed since it will be lost.
+  * The task count is decremented.
+  */
+-static inline void task_free(struct task *t)
++static inline void __task_free(struct task *t)
+ {
+       pool_free(pool_head_task, t);
+       if (unlikely(stopping))
+@@ -238,6 +243,18 @@ static inline void task_free(struct task *t)
+       HA_ATOMIC_SUB(&nb_tasks, 1);
+ }
++static inline void task_free(struct task *t)
++{
++      /* There's no need to protect t->state with a lock, as the task
++       * has to run on the current thread.
++       */
++      if (t == curr_task || !(t->state & TASK_RUNNING))
++              __task_free(t);
++      else
++              t->process = NULL;
++}
++
++
+ /* Place <task> into the wait queue, where it may already be. If the expiration
+  * timer is infinite, do nothing and rely on wake_expired_task to clean up.
+  */
+diff --git a/src/task.c b/src/task.c
+index fd9acf66..3d021bb4 100644
+--- a/src/task.c
++++ b/src/task.c
+@@ -39,6 +39,7 @@ unsigned int nb_tasks_cur = 0;     /* copy of the tasks count */
+ unsigned int niced_tasks = 0;      /* number of niced tasks in the run queue */
+ THREAD_LOCAL struct task *curr_task = NULL; /* task currently running or NULL */
++THREAD_LOCAL struct eb32sc_node *rq_next = NULL; /* Next task to be potentially run */
+ __decl_hathreads(HA_SPINLOCK_T __attribute__((aligned(64))) rq_lock); /* spin lock related to run queue */
+ __decl_hathreads(HA_SPINLOCK_T __attribute__((aligned(64))) wq_lock); /* spin lock related to wait queue */
+@@ -186,7 +187,6 @@ void process_runnable_tasks()
+       struct task *t;
+       int i;
+       int max_processed;
+-      struct eb32sc_node *rq_next;
+       struct task *local_tasks[16];
+       int local_tasks_count;
+       int final_tasks_count;
+@@ -227,8 +227,14 @@ void process_runnable_tasks()
+                        */
+                       if (likely(t->process == process_stream))
+                               t = process_stream(t);
+-                      else
+-                              t = t->process(t);
++                      else {
++                              if (t->process != NULL)
++                                      t = t->process(t);
++                              else {
++                                      __task_free(t);
++                                      t = NULL;
++                              }
++                      }
+                       curr_task = NULL;
+                       if (likely(t != NULL)) {
+@@ -309,8 +315,14 @@ void process_runnable_tasks()
+                       curr_task = t;
+                       if (likely(t->process == process_stream))
+                               t = process_stream(t);
+-                      else
+-                              t = t->process(t);
++                      else {
++                              if (t->process != NULL)
++                                      t = t->process(t);
++                              else {
++                                      __task_free(t);
++                                      t = NULL;
++                              }
++                      }
+                       curr_task = NULL;
+                       if (t)
+                               local_tasks[final_tasks_count++] = t;
diff --git a/net/haproxy/patches/0014-BUG-MINOR-lua-schedule-socket-task-upon-lua-connect.patch b/net/haproxy/patches/0014-BUG-MINOR-lua-schedule-socket-task-upon-lua-connect.patch
new file mode 100644 (file)
index 0000000..f7e3cf3
--- /dev/null
@@ -0,0 +1,48 @@
+commit 52ec3578c3ddc688ae14da3cd3e7e351494603d8
+Author: PiBa-NL <PiBa.NL.dev@gmail.com>
+Date:   Sat May 5 23:51:42 2018 +0200
+
+    BUG/MINOR: lua: schedule socket task upon lua connect()
+    
+    The parameters like server-address, port and timeout should be set before
+    process_stream task is called to avoid the stream being 'closed' before it
+    got initialized properly. This is most clearly visible when running with
+    tune.lua.forced-yield=1.. So scheduling the task should not be done when
+    creating the lua socket, but when connect is called. The error
+    "socket: not yet initialised, you can't set timeouts." would then appear.
+    
+    Below code for example also shows this issue, as the sleep will
+    yield the lua code:
+      local con = core.tcp()
+      core.sleep(1)
+      con:settimeout(10)
+    
+    (cherry picked from commit 706d5ee0c366787536213ccd6dea264d20b76a22)
+    [wt: must be backported to 1.7 and 1.6 as well with a different patch,
+     see https://www.mail-archive.com/haproxy@formilux.org/msg29924.html]
+    Signed-off-by: Willy Tarreau <w@1wt.eu>
+
+diff --git a/src/hlua.c b/src/hlua.c
+index 0100e7cf..5cc918c9 100644
+--- a/src/hlua.c
++++ b/src/hlua.c
+@@ -2415,6 +2415,10 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
+               WILL_LJMP(luaL_error(L, "out of memory"));
+       }
+       xref_unlock(&socket->xref, peer);
++
++      task_wakeup(s->task, TASK_WOKEN_INIT);
++      /* Return yield waiting for connection. */
++
+       WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
+       return 0;
+@@ -2566,8 +2570,6 @@ __LJMP static int hlua_socket_new(lua_State *L)
+       strm->flags |= SF_DIRECT | SF_ASSIGNED | SF_ADDR_SET | SF_BE_ASSIGNED;
+       strm->target = &socket_tcp.obj_type;
+-      task_wakeup(strm->task, TASK_WOKEN_INIT);
+-      /* Return yield waiting for connection. */
+       return 1;
+  out_fail_stream: