]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: xref/lua: Use xref for referencing cosocket relation between stream and lua
authorThierry FOURNIER <thierry.fournier@ozon.io>
Mon, 11 Sep 2017 16:37:23 +0000 (18:37 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 11 Sep 2017 16:59:40 +0000 (18:59 +0200)
This relation will ensure that each was informed about death of another one.

doc/internals/lua_socket.fig
doc/internals/lua_socket.pdf
include/types/applet.h
include/types/hlua.h
src/hlua.c

index bed20e32d2e33e8188282188d89f2e3a72d9133f..2ecb0f84163d0135b781193f0cd40b99e183742d 100644 (file)
@@ -7,116 +7,107 @@ A4
 Single
 -2
 1200 2
-6 7020 8775 9675 9405
-4 0 0 50 -1 12 12 0.0000 4 165 2400 7020 8910 update_tcp_handler()\001
-4 0 0 50 -1 16 12 0.0000 4 195 2640 7020 9105 Called on each change on the \001
-4 0 0 50 -1 16 12 0.0000 4 195 1830 7020 9345 tcp connection state.\001
--6
-6 7020 9675 10170 10080
-4 0 0 50 -1 12 12 0.0000 4 165 2160 7020 9810 hlua_tcp_release()\001
-4 0 0 50 -1 16 12 0.0000 4 195 3150 7020 10005 Called when the applet is destroyed.\001
--6
-6 765 8730 3195 9450
-4 0 0 50 -1 12 12 0.0000 4 165 1560 765 8910 hlua_tcp_gc()\001
-4 0 0 50 -1 16 12 0.0000 4 195 2430 765 9105 Called just before the object\001
-4 0 0 50 -1 16 12 0.0000 4 195 840 765 9345 garbaging\001
--6
-6 900 3555 2340 4365
+6 1125 2745 2565 3555
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        900 3555 2340 3555 2340 4365 900 4365 900 3555
-4 0 0 50 -1 16 12 0.0000 4 180 1080 990 4005 lua_State *T\001
-4 0 0 50 -1 18 12 0.0000 4 150 990 990 3735 struct hlua\001
-4 0 0 50 -1 16 12 0.0000 4 195 1245 990 4275 stop_list *stop\001
+        1125 2745 2565 2745 2565 3555 1125 3555 1125 2745
+4 0 0 50 -1 16 12 0.0000 4 180 1080 1215 3195 lua_State *T\001
+4 0 0 50 -1 18 12 0.0000 4 150 990 1215 2925 struct hlua\001
+4 0 0 50 -1 16 12 0.0000 4 195 1245 1215 3465 stop_list *stop\001
 -6
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
-       1 1 1.00 60.00 120.00
-        10530 6750 8910 6570
+6 7560 4365 10620 5265
+2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
+        7650 4635 10530 4635 10530 5175 7650 5175 7650 4635
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        10440 6390 13320 6390 13320 6930 10440 6930 10440 6390
-2 1 1 4 4 7 50 -1 -1 4.000 0 0 -1 0 0 2
-        6480 2745 6480 10035
+        7560 4365 10620 4365 10620 5265 7560 5265 7560 4365
+4 0 0 50 -1 18 12 0.0000 4 195 2565 7740 4815 struct stream_interface si[0]\001
+4 0 0 50 -1 16 12 0.0000 4 195 1725 7740 5085 enum obj_type *end\001
+4 0 0 50 -1 18 12 0.0000 4 150 1215 7650 4545 struct stream\001
+-6
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-        0 5310 2520 5310
+        225 4500 2745 4500
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-        0 5850 2520 5850
+        225 5040 2745 5040
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-        0 5580 2520 5580
+        225 4770 2745 4770
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
        1 1 1.00 60.00 120.00
-        6840 7245 4635 5310
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4
-        6885 7110 6840 7155 6840 7335 6885 7380
+        1935 5715 7740 6705
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
        1 1 1.00 60.00 120.00
-        1575 6525 10350 6210
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
-       1 1 1.00 60.00 120.00
-        2295 4230 3375 4905
+        2520 3420 3600 4095
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        0 5040 2520 5040 2520 7830 0 7830 0 5040
+        225 4230 2745 4230 2745 7020 225 7020 225 4230
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-        0 7110 2520 7110
+        225 6300 2745 6300
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
-        0 7470 2520 7470
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        90 6120 2430 6120 2430 6975 90 6975 90 6120
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        3375 4815 5850 4815 5850 5310 3375 5310 3375 4815
+        225 6660 2745 6660
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        6705 6480 8910 6480 8910 8010 6705 8010 6705 6480
+        1035 2205 2655 2205 2655 3645 1035 3645 1035 2205
+2 1 1 4 4 7 500 -1 -1 4.000 0 0 -1 0 0 2
+        4860 1935 4860 9225
 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
        1 1 1.00 60.00 120.00
-        6840 7605 2430 6840
+        7695 6435 5760 4410
+2 2 0 1 0 7 50 -1 20 0.000 0 0 -1 0 0 5
+        3600 3915 6075 3915 6075 4410 3600 4410 3600 3915
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        9450 5040 9225 5670
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4
+        7740 6300 7695 6345 7695 6525 7740 6570
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        810 3015 2430 3015 2430 4455 810 4455 810 3015
+        7560 5670 9765 5670 9765 7200 7560 7200 7560 5670
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        6795 6750 8820 6750 8820 7920 6795 7920 6795 6750
+        7650 5940 9675 5940 9675 7110 7650 7110 7650 5940
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        3060 630 4500 630 4500 1440 3060 1440 3060 630
+        315 5310 2655 5310 2655 6165 315 6165 315 5310
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+       1 1 1.00 60.00 120.00
+        7830 6840 2565 5580
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        2970 90 4635 90 4635 1575 2970 1575 2970 90
+        7740 6705 9540 6705 9540 6930 7740 6930 7740 6705
 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
-        10350 6120 13410 6120 13410 7020 10350 7020 10350 6120
-3 0 1 1 13 7 50 -1 -1 1.000 0 1 0 2
-       5 1 1.00 60.00 120.00
-        6885 8010 6885 8910
-        0.000 0.000
-3 0 1 1 13 7 50 -1 -1 1.000 0 1 0 3
-       5 1 1.00 60.00 120.00
-        6750 8010 6750 9675 6885 9810
-        0.000 1.000 0.000
+        405 5580 2565 5580 2565 5805 405 5805 405 5580
 3 0 0 1 0 7 50 -1 -1 0.000 0 1 0 5
        1 1 1.00 60.00 120.00
-        990 3915 540 4140 495 4365 540 4725 585 5040
+        1215 3105 765 3330 720 3555 765 3915 810 4230
         0.000 1.000 1.000 1.000 0.000
 3 0 1 1 13 7 50 -1 -1 1.000 0 1 0 3
        5 1 1.00 60.00 120.00
-        450 7830 450 8595 675 8914
+        675 7020 675 7785 900 8104
+        0.000 1.000 0.000
+3 0 1 1 13 7 50 -1 -1 1.000 0 1 0 2
+       5 1 1.00 60.00 120.00
+        7740 7200 7740 8100
+        0.000 0.000
+3 0 1 1 13 7 50 -1 -1 1.000 0 1 0 3
+       5 1 1.00 60.00 120.00
+        7605 7200 7605 8865 7740 9000
         0.000 1.000 0.000
-4 0 0 50 -1 18 12 0.0000 4 195 2565 10530 6570 struct stream_interface si[0]\001
-4 0 0 50 -1 16 12 0.0000 4 195 1725 10530 6840 enum obj_type *end\001
-4 0 0 50 -1 18 12 0.0000 4 150 885 90 5220 stack Lua\001
-4 0 0 50 -1 16 12 0.0000 4 195 1140 90 5490 stack entry 0\001
-4 0 0 50 -1 16 12 0.0000 4 195 1140 90 5760 stack entry 1\001
-4 0 0 50 -1 16 12 0.0000 4 195 1140 90 6030 stack entry 2\001
-4 0 0 50 -1 18 12 0.0000 4 195 1200 6795 6660 struct appctx\001
-4 0 0 50 -1 18 12 0.0000 4 195 1695 180 6300 struct hlua_socket\001
-4 0 0 50 -1 16 12 0.0000 4 150 1470 180 6570 struct session *s\001
-4 0 0 50 -1 16 12 0.0000 4 195 1140 90 7380 stack entry 3\001
-4 0 0 50 -1 16 12 0.0000 4 195 1140 90 7740 stack entry 4\001
-4 1 12 50 -1 12 9 5.6723 4 135 540 2925 4545 (list)\001
-4 0 0 50 -1 18 12 0.0000 4 195 2205 3465 4995 struct hlua_socket_com\001
-4 1 12 50 -1 12 9 5.5851 4 135 540 5265 5760 (list)\001
-4 0 0 50 -1 18 12 0.0000 4 150 1305 900 3240 struct session\001
-4 0 0 50 -1 16 12 0.0000 4 150 1440 900 3465 struct task *task\001
-4 0 0 50 -1 16 12 0.0000 4 150 1440 3465 5220 struct task *task\001
-4 0 0 50 -1 18 12 0.0000 4 150 1110 6885 6930 struct <lua>\001
-4 0 0 50 -1 16 12 0.0000 4 195 1620 6885 7425 struct hlua_tcp *wr\001
-4 0 0 50 -1 16 12 0.0000 4 195 1590 6885 7200 struct hlua_tcp *rd\001
-4 0 0 50 -1 16 12 0.0000 4 180 1845 6885 7650 struct hlua_socket *s\001
-4 0 0 50 -1 18 12 0.0000 4 195 1470 3060 270 struct hlua_task\001
-4 0 0 50 -1 16 12 0.0000 4 150 1440 3060 540 struct task *task\001
-4 0 0 50 -1 16 12 0.0000 4 180 1080 3150 1080 lua_State *T\001
-4 0 0 50 -1 18 12 0.0000 4 150 990 3150 810 struct hlua\001
-4 0 0 50 -1 16 12 0.0000 4 195 1245 3150 1350 stop_list *stop\001
-4 0 0 50 -1 18 12 0.0000 4 150 1305 10440 6300 struct session\001
+4 0 0 50 -1 18 12 0.0000 4 150 885 315 4410 stack Lua\001
+4 0 0 50 -1 16 12 0.0000 4 195 1140 315 4680 stack entry 0\001
+4 0 0 50 -1 16 12 0.0000 4 195 1140 315 4950 stack entry 1\001
+4 0 0 50 -1 16 12 0.0000 4 195 1140 315 5220 stack entry 2\001
+4 0 0 50 -1 18 12 0.0000 4 195 1695 405 5490 struct hlua_socket\001
+4 0 0 50 -1 16 12 0.0000 4 195 1140 315 6570 stack entry 3\001
+4 0 0 50 -1 16 12 0.0000 4 195 1140 315 6930 stack entry 4\001
+4 1 12 50 -1 12 9 5.6723 4 135 540 3150 3735 (list)\001
+4 0 0 50 -1 18 12 0.0000 4 150 1305 1125 2430 struct session\001
+4 0 0 50 -1 16 12 0.0000 4 150 1440 1125 2655 struct task *task\001
+4 0 0 50 -1 12 12 0.0000 4 165 1560 990 8100 hlua_tcp_gc()\001
+4 0 0 50 -1 16 12 0.0000 4 195 2430 990 8295 Called just before the object\001
+4 0 0 50 -1 16 12 0.0000 4 195 840 990 8535 garbaging\001
+4 1 12 50 -1 12 9 5.5327 4 135 540 6390 4905 (list)\001
+4 0 0 50 -1 18 12 0.0000 4 195 2205 3690 4095 struct hlua_socket_com\001
+4 0 0 50 -1 16 12 0.0000 4 150 1440 3690 4320 struct task *task\001
+4 0 0 50 -1 18 12 0.0000 4 195 1200 7650 5850 struct appctx\001
+4 0 0 50 -1 18 12 0.0000 4 150 1110 7740 6120 struct <lua>\001
+4 0 0 50 -1 16 12 0.0000 4 195 1620 7740 6615 struct hlua_tcp *wr\001
+4 0 0 50 -1 16 12 0.0000 4 195 1590 7740 6390 struct hlua_tcp *rd\001
+4 0 0 50 -1 12 12 0.0000 4 165 2160 7875 9000 hlua_tcp_release()\001
+4 0 0 50 -1 16 12 0.0000 4 195 3150 7875 9195 Called when the applet is destroyed.\001
+4 0 0 50 -1 12 12 0.0000 4 165 2400 7875 8100 update_tcp_handler()\001
+4 0 0 50 -1 16 12 0.0000 4 195 2640 7875 8295 Called on each change on the \001
+4 0 0 50 -1 16 12 0.0000 4 195 1830 7875 8535 tcp connection state.\001
+4 0 0 50 -1 16 12 0.0000 4 150 1350 495 5760 struct xref *xref\001
+4 0 0 50 -1 16 12 0.0000 4 150 1350 7830 6885 struct xref *xref\001
index aca7ff152a4bae7721d17ebf1b64cc03b0c25e5a..e3b80ee0af7303a8e90aadd601bb11c8df8be937 100644 (file)
Binary files a/doc/internals/lua_socket.pdf and b/doc/internals/lua_socket.pdf differ
index e81cff71abfd6e79666047b14557a9559859ec09..347c71a0921aa152425034829f229b416f33fc91 100644 (file)
@@ -29,6 +29,7 @@
 #include <common/buffer.h>
 #include <common/chunk.h>
 #include <common/config.h>
+#include <common/xref.h>
 
 struct appctx;
 
@@ -73,7 +74,7 @@ struct appctx {
                } peers;                        /* used by the peers applet */
                struct {
                        int connected;
-                       struct hlua_socket *socket;
+                       struct xref xref; /* cross reference with the Lua object owner. */
                        struct list wake_on_read;
                        struct list wake_on_write;
                        int die;
index 214651fe2892d09f5bd6f4492fae1b2bd9662a72..a0a1e26561f2093c2f629b69c3642949cf8db514 100644 (file)
@@ -6,6 +6,8 @@
 #include <lua.h>
 #include <lauxlib.h>
 
+#include <common/xref.h>
+
 #include <types/proxy.h>
 #include <types/server.h>
 
@@ -159,7 +161,7 @@ struct hlua_sleep {
  * SSL I/O. It uses a fake stream.
  */
 struct hlua_socket {
-       struct stream *s; /* Stream used for socket I/O. */
+       struct xref xref; /* cross reference with the stream used for socket I/O. */
        luaL_Buffer b; /* buffer used to prepare strings. */
 };
 
index 4299487155da5577f55c99316b4fc8f774b92f16..98fed3bc36dce378f03df834c8381400e3bc91a4 100644 (file)
@@ -24,6 +24,7 @@
 #include <ebpttree.h>
 
 #include <common/cfgparse.h>
+#include <common/xref.h>
 
 #include <types/cli.h>
 #include <types/hlua.h>
@@ -1604,8 +1605,7 @@ static void hlua_socket_handler(struct appctx *appctx)
 static void hlua_socket_release(struct appctx *appctx)
 {
        /* Remove my link in the original object. */
-       if (appctx->ctx.hlua_cosocket.socket)
-               appctx->ctx.hlua_cosocket.socket->s = NULL;
+       xref_disconnect(&appctx->ctx.hlua_cosocket.xref);
 
        /* Wake all the task waiting for me. */
        hlua_com_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
@@ -1622,20 +1622,24 @@ __LJMP static int hlua_socket_gc(lua_State *L)
 {
        struct hlua_socket *socket;
        struct appctx *appctx;
+       struct xref *peer;
 
        MAY_LJMP(check_args(L, 1, "__gc"));
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
-       if (!socket->s)
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
                return 0;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
 
-       /* Remove all reference between the Lua stack and the coroutine stream. */
-       appctx = objt_appctx(socket->s->si[0].end);
-       socket->s = NULL;
-       appctx->ctx.hlua_cosocket.socket = NULL;
+       /* Set the flag which destroy the session. */
        appctx->ctx.hlua_cosocket.die = 1;
        appctx_wakeup(appctx);
 
+       /* Remove all reference between the Lua stack and the coroutine stream. */
+       xref_disconnect(&socket->xref);
        return 0;
 }
 
@@ -1646,20 +1650,24 @@ __LJMP static int hlua_socket_close(lua_State *L)
 {
        struct hlua_socket *socket;
        struct appctx *appctx;
+       struct xref *peer;
 
        MAY_LJMP(check_args(L, 1, "close"));
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
-       if (!socket->s)
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
                return 0;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
 
-       /* Close the stream and remove the associated stop task. */
-       appctx = objt_appctx(socket->s->si[0].end);
-       appctx->ctx.hlua_cosocket.socket = NULL;
-       socket->s = NULL;
+       /* Set the flag which destroy the session. */
        appctx->ctx.hlua_cosocket.die = 1;
        appctx_wakeup(appctx);
 
+       /* Remove all reference between the Lua stack and the coroutine stream. */
+       xref_disconnect(&socket->xref);
        return 0;
 }
 
@@ -1688,17 +1696,26 @@ __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua
        int len2;
        int skip_at_end = 0;
        struct channel *oc;
+       struct stream_interface *si;
+       struct stream *s;
+       struct xref *peer;
 
        /* Check if this lua stack is schedulable. */
        if (!hlua || !hlua->task)
                WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
                                      "'frontend', 'backend' or 'task'"));
 
-       /* check for connection closed. If some data where read, return it. */
-       if (!socket->s)
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
                goto connection_closed;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
 
-       oc = &socket->s->res;
+       oc = &s->res;
        if (wanted == HLSR_READ_LINE) {
                /* Read line. */
                nblk = bo_getline_nc(oc, &blk1, &len1, &blk2, &len2);
@@ -1766,8 +1783,8 @@ __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua
        bo_skip(oc, len + skip_at_end);
 
        /* Don't wait anything. */
-       stream_int_notify(&socket->s->si[0]);
-       stream_int_update_applet(&socket->s->si[0]);
+       stream_int_notify(&s->si[0]);
+       stream_int_update_applet(&s->si[0]);
 
        /* If the pattern reclaim to read all the data
         * in the connection, got out.
@@ -1794,7 +1811,7 @@ connection_closed:
 
 connection_empty:
 
-       appctx = objt_appctx(socket->s->si[0].end);
+       appctx = objt_appctx(s->si[0].end);
        if (!hlua_com_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task))
                WILL_LJMP(luaL_error(L, "out of memory"));
        WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
@@ -1883,6 +1900,9 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
        int len;
        int send_len;
        int sent;
+       struct xref *peer;
+       struct stream_interface *si;
+       struct stream *s;
 
        /* Check if this lua stack is schedulable. */
        if (!hlua || !hlua->task)
@@ -1894,8 +1914,19 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
        buf = MAY_LJMP(luaL_checklstring(L, 2, &buf_len));
        sent = MAY_LJMP(luaL_checkinteger(L, 3));
 
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
+               lua_pushinteger(L, -1);
+               return 1;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
+
        /* Check for connection close. */
-       if (!socket->s || channel_output_closed(&socket->s->req)) {
+       if (channel_output_closed(&s->req)) {
                lua_pushinteger(L, -1);
                return 1;
        }
@@ -1911,16 +1942,16 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
        /* Check if the buffer is avalaible because HAProxy doesn't allocate
         * the request buffer if its not required.
         */
-       if (socket->s->req.buf->size == 0) {
+       if (s->req.buf->size == 0) {
                appctx = hlua->task->context;
-               if (!channel_alloc_buffer(&socket->s->req, &appctx->buffer_wait))
+               if (!channel_alloc_buffer(&s->req, &appctx->buffer_wait))
                        goto hlua_socket_write_yield_return;
        }
 
        /* Check for avalaible space. */
-       len = buffer_total_space(socket->s->req.buf);
+       len = buffer_total_space(s->req.buf);
        if (len <= 0) {
-               appctx = objt_appctx(socket->s->si[0].end);
+               appctx = objt_appctx(s->si[0].end);
                if (!hlua_com_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
                        WILL_LJMP(luaL_error(L, "out of memory"));
                goto hlua_socket_write_yield_return;
@@ -1929,7 +1960,7 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
        /* send data */
        if (len < send_len)
                send_len = len;
-       len = bi_putblk(&socket->s->req, buf+sent, send_len);
+       len = bi_putblk(&s->req, buf+sent, send_len);
 
        /* "Not enough space" (-1), "Buffer too little to contain
         * the data" (-2) are not expected because the available length
@@ -1938,7 +1969,7 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
         */
        if (len <= 0) {
                if (len == -1)
-                       socket->s->req.flags |= CF_WAKE_WRITE;
+                       s->req.flags |= CF_WAKE_WRITE;
 
                MAY_LJMP(hlua_socket_close(L));
                lua_pop(L, 1);
@@ -1947,11 +1978,11 @@ static int hlua_socket_write_yield(struct lua_State *L,int status, lua_KContext
        }
 
        /* update buffers. */
-       stream_int_notify(&socket->s->si[0]);
-       stream_int_update_applet(&socket->s->si[0]);
+       stream_int_notify(&s->si[0]);
+       stream_int_update_applet(&s->si[0]);
 
-       socket->s->req.rex = TICK_ETERNITY;
-       socket->s->res.wex = TICK_ETERNITY;
+       s->req.rex = TICK_ETERNITY;
+       s->res.wex = TICK_ETERNITY;
 
        /* Update length sent. */
        lua_pop(L, 1);
@@ -2096,18 +2127,27 @@ __LJMP static int hlua_socket_getpeername(struct lua_State *L)
 {
        struct hlua_socket *socket;
        struct connection *conn;
+       struct xref *peer;
+       struct appctx *appctx;
+       struct stream_interface *si;
+       struct stream *s;
 
        MAY_LJMP(check_args(L, 1, "getpeername"));
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
 
-       /* Check if the tcp object is avalaible. */
-       if (!socket->s) {
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
                lua_pushnil(L);
                return 1;
        }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
 
-       conn = objt_conn(socket->s->si[1].end);
+       conn = objt_conn(s->si[1].end);
        if (!conn) {
                lua_pushnil(L);
                return 1;
@@ -2127,18 +2167,27 @@ static int hlua_socket_getsockname(struct lua_State *L)
 {
        struct hlua_socket *socket;
        struct connection *conn;
+       struct appctx *appctx;
+       struct xref *peer;
+       struct stream_interface *si;
+       struct stream *s;
 
        MAY_LJMP(check_args(L, 1, "getsockname"));
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
 
-       /* Check if the tcp object is avalaible. */
-       if (!socket->s) {
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
                lua_pushnil(L);
                return 1;
        }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
 
-       conn = objt_conn(socket->s->si[1].end);
+       conn = objt_conn(s->si[1].end);
        if (!conn) {
                lua_pushnil(L);
                return 1;
@@ -2165,16 +2214,31 @@ __LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua
 {
        struct hlua_socket *socket = MAY_LJMP(hlua_checksocket(L, 1));
        struct hlua *hlua = hlua_gethlua(L);
+       struct xref *peer;
        struct appctx *appctx;
+       struct stream_interface *si;
+       struct stream *s;
+
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
+               lua_pushnil(L);
+               lua_pushstring(L, "Can't connect");
+               return 2;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
 
        /* Check for connection close. */
-       if (!hlua || !socket->s || channel_output_closed(&socket->s->req)) {
+       if (!hlua || channel_output_closed(&s->req)) {
                lua_pushnil(L);
                lua_pushstring(L, "Can't connect");
                return 2;
        }
 
-       appctx = objt_appctx(socket->s->si[0].end);
+       appctx = objt_appctx(s->si[0].end);
 
        /* Check for connection established. */
        if (appctx->ctx.hlua_cosocket.connected) {
@@ -2199,27 +2263,37 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
        struct appctx *appctx;
        int low, high;
        struct sockaddr_storage *addr;
+       struct xref *peer;
+       struct stream_interface *si;
+       struct stream *s;
 
        if (lua_gettop(L) < 2)
                WILL_LJMP(luaL_error(L, "connect: need at least 2 arguments"));
 
        /* Get args. */
        socket  = MAY_LJMP(hlua_checksocket(L, 1));
-
-       /* The socket may be destroy. */
-       if (!socket->s)
-               return 0;
-
        ip      = MAY_LJMP(luaL_checkstring(L, 2));
        if (lua_gettop(L) >= 3)
                port = MAY_LJMP(luaL_checkinteger(L, 3));
 
-       conn = si_alloc_conn(&socket->s->si[1]);
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
+               lua_pushnil(L);
+               return 1;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
+
+       /* Initialise connection. */
+       conn = si_alloc_conn(&s->si[1]);
        if (!conn)
                WILL_LJMP(luaL_error(L, "connect: internal error"));
 
        /* needed for the connection not to be closed */
-       conn->target = socket->s->target;
+       conn->target = s->target;
 
        /* Parse ip address. */
        addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, 0);
@@ -2243,13 +2317,13 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
        }
 
        hlua = hlua_gethlua(L);
-       appctx = objt_appctx(socket->s->si[0].end);
+       appctx = objt_appctx(s->si[0].end);
 
        /* inform the stream that we want to be notified whenever the
         * connection completes.
         */
-       si_applet_cant_get(&socket->s->si[0]);
-       si_applet_cant_put(&socket->s->si[0]);
+       si_applet_cant_get(&s->si[0]);
+       si_applet_cant_put(&s->si[0]);
        appctx_wakeup(appctx);
 
        hlua->flags |= HLUA_MUST_GC;
@@ -2265,10 +2339,26 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
 __LJMP static int hlua_socket_connect_ssl(struct lua_State *L)
 {
        struct hlua_socket *socket;
+       struct xref *peer;
+       struct appctx *appctx;
+       struct stream_interface *si;
+       struct stream *s;
 
        MAY_LJMP(check_args(L, 3, "connect_ssl"));
        socket  = MAY_LJMP(hlua_checksocket(L, 1));
-       socket->s->target = &socket_ssl.obj_type;
+
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
+               lua_pushnil(L);
+               return 1;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
+
+       s->target = &socket_ssl.obj_type;
        return MAY_LJMP(hlua_socket_connect(L));
 }
 #endif
@@ -2282,16 +2372,32 @@ __LJMP static int hlua_socket_settimeout(struct lua_State *L)
 {
        struct hlua_socket *socket;
        int tmout;
+       struct xref *peer;
+       struct appctx *appctx;
+       struct stream_interface *si;
+       struct stream *s;
 
        MAY_LJMP(check_args(L, 2, "settimeout"));
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
        tmout = MAY_LJMP(luaL_checkinteger(L, 2)) * 1000;
 
-       socket->s->req.rto = tmout;
-       socket->s->req.wto = tmout;
-       socket->s->res.rto = tmout;
-       socket->s->res.wto = tmout;
+       /* check for connection break. If some data where read, return it. */
+       peer = xref_get_peer(&socket->xref);
+       if (!peer) {
+               xref_disconnect(&socket->xref);
+               hlua_pusherror(L, "socket: not yet initialised, you can't set timeouts.");
+               WILL_LJMP(lua_error(L));
+               return 0;
+       }
+       appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
+       si = appctx->owner;
+       s = si_strm(si);
+
+       s->req.rto = tmout;
+       s->req.wto = tmout;
+       s->res.rto = tmout;
+       s->res.wto = tmout;
 
        return 0;
 }
@@ -2332,7 +2438,6 @@ __LJMP static int hlua_socket_new(lua_State *L)
                goto out_fail_conf;
        }
 
-       appctx->ctx.hlua_cosocket.socket = socket;
        appctx->ctx.hlua_cosocket.connected = 0;
        appctx->ctx.hlua_cosocket.die = 0;
        LIST_INIT(&appctx->ctx.hlua_cosocket.wake_on_write);
@@ -2351,8 +2456,8 @@ __LJMP static int hlua_socket_new(lua_State *L)
                goto out_fail_stream;
        }
 
-       /* Configure an empty Lua for the stream. */
-       socket->s = strm;
+       /* Initialise cross reference between stream and Lua socket object. */
+       xref_create(&socket->xref, &appctx->ctx.hlua_cosocket.xref);
 
        /* Configure "right" stream interface. this "si" is used to connect
         * and retrieve data from the server. The connection is initialized