MEDIUM: threads/lua: Cannot acces to the socket if we try to access from another...
authorThierry FOURNIER <thierry.fournier@ozon.io>
Wed, 12 Jul 2017 10:10:44 +0000 (12:10 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 12:58:32 +0000 (13:58 +0100)
We have two y for nsuring that the data is not concurently manipulated:
 - locks
 - running task on the same thread.
locks are expensives, it is better to avoid it.

This patch cecks that the Lua task run on the same thread that
the stream associated to the coprocess.

TODO: in a next version, the error should be replaced by a yield
and thread migration request.

include/types/hlua.h
src/hlua.c

index 74dcf00..e8daf53 100644 (file)
@@ -156,6 +156,7 @@ struct hlua_sleep {
 struct hlua_socket {
        struct xref xref; /* cross reference with the stream used for socket I/O. */
        luaL_Buffer b; /* buffer used to prepare strings. */
+       unsigned long tid; /* Store the thread id which creates the socket. */
 };
 
 struct hlua_concat {
index 3bb46bb..1d14e54 100644 (file)
@@ -1630,6 +1630,13 @@ __LJMP static int hlua_socket_close(lua_State *L)
        MAY_LJMP(check_args(L, 1, "close"));
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
+
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
                xref_disconnect(&socket->xref);
@@ -1680,6 +1687,12 @@ __LJMP static int hlua_socket_receive_yield(struct lua_State *L, int status, lua
                WILL_LJMP(luaL_error(L, "The 'receive' function is only allowed in "
                                      "'frontend', 'backend' or 'task'"));
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for connection break. If some data where read, return it. */
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
@@ -1822,6 +1835,12 @@ __LJMP static int hlua_socket_receive(struct lua_State *L)
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for pattern. */
        if (lua_gettop(L) >= 2) {
                type = lua_type(L, 2);
@@ -1889,6 +1908,12 @@ 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 if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for connection break. If some data where read, return it. */
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
@@ -2111,6 +2136,12 @@ __LJMP static int hlua_socket_getpeername(struct lua_State *L)
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for connection break. If some data where read, return it. */
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
@@ -2151,6 +2182,12 @@ static int hlua_socket_getsockname(struct lua_State *L)
 
        socket = MAY_LJMP(hlua_checksocket(L, 1));
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for connection break. If some data where read, return it. */
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
@@ -2194,6 +2231,12 @@ __LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua
        struct stream_interface *si;
        struct stream *s;
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for connection break. If some data where read, return it. */
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
@@ -2206,6 +2249,12 @@ __LJMP static int hlua_socket_connect_yield(struct lua_State *L, int status, lua
        si = appctx->owner;
        s = si_strm(si);
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* Check for connection close. */
        if (!hlua || channel_output_closed(&s->req)) {
                lua_pushnil(L);
@@ -2247,6 +2296,13 @@ __LJMP static int hlua_socket_connect(struct lua_State *L)
 
        /* Get args. */
        socket  = MAY_LJMP(hlua_checksocket(L, 1));
+
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        ip      = MAY_LJMP(luaL_checkstring(L, 2));
        if (lua_gettop(L) >= 3)
                port = MAY_LJMP(luaL_checkinteger(L, 3));
@@ -2357,6 +2413,12 @@ __LJMP static int hlua_socket_settimeout(struct lua_State *L)
        socket = MAY_LJMP(hlua_checksocket(L, 1));
        tmout = MAY_LJMP(luaL_checkinteger(L, 2)) * 1000;
 
+       /* Check if we run on the same thread than the xreator thread.
+        * We cannot access to the socket if the thread is different.
+        */
+       if (socket->tid != tid)
+               WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+
        /* check for connection break. If some data where read, return it. */
        peer = xref_get_peer(&socket->xref);
        if (!peer) {
@@ -2395,6 +2457,7 @@ __LJMP static int hlua_socket_new(lua_State *L)
        socket = MAY_LJMP(lua_newuserdata(L, sizeof(*socket)));
        lua_rawseti(L, -2, 0);
        memset(socket, 0, sizeof(*socket));
+       socket->tid = tid;
 
        /* Check if the various memory pools are intialized. */
        if (!pool2_stream || !pool2_buffer) {