From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladislav Shpilevoy Subject: [PATCH v2 4/4] session: outdate a session of a closed connection Date: Tue, 11 Dec 2018 19:10:23 +0300 Message-Id: <0bf15f316a62b1c78a0f4b8c17a0b33a741b142f.1544544183.git.v.shpilevoy@tarantool.org> In-Reply-To: References: In-Reply-To: References: To: tarantool-patches@freelists.org Cc: vdavydov.dev@gmail.com List-ID: Once a connection is closed, a long-running user request can not learn about this occasion. Even box.sesion.push() still works. This patch makes such disconnected session 'rotten'. So a user can determine if a connection is closed by looking at session.fd() == -1, or checking for errors from box.session.push(). Closes #3859 --- src/box/iproto.cc | 27 ++++++++++++++++++++--- test/box/push.result | 50 ++++++++++++++++++++++++++++++++++++++++++ test/box/push.test.lua | 22 +++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/src/box/iproto.cc b/src/box/iproto.cc index e6eefc3d8..8fddc76ef 100644 --- a/src/box/iproto.cc +++ b/src/box/iproto.cc @@ -1239,14 +1239,35 @@ tx_fiber_init(struct session *session, uint64_t sync) fiber_set_user(f, &session->credentials); } +static int +iproto_disconnected_session_push(struct session *session, uint64_t sync, + struct port *port) +{ + (void) session; + (void) sync; + (void) port; + diag_set(ClientError, ER_NO_CONNECTION); + return -1; +} + +static const struct session_vtab iproto_disconnected_session_vtab = { + /* .push = */ iproto_disconnected_session_push, + /* .fd = */ generic_session_fd, + /* .sync = */ generic_session_sync, +}; + static void tx_process_disconnect(struct cmsg *m) { struct iproto_connection *con = container_of(m, struct iproto_connection, disconnect_msg); - if (con->session != NULL && !rlist_empty(&session_on_disconnect)) { - tx_fiber_init(con->session, 0); - session_run_on_disconnect_triggers(con->session); + if (con->session != NULL) { + session_set_type(con->session, SESSION_TYPE_BINARY, + &iproto_disconnected_session_vtab); + if (! rlist_empty(&session_on_disconnect)) { + tx_fiber_init(con->session, 0); + session_run_on_disconnect_triggers(con->session); + } } } diff --git a/test/box/push.result b/test/box/push.result index af730c1a7..6f858f38a 100644 --- a/test/box/push.result +++ b/test/box/push.result @@ -497,6 +497,56 @@ box.schema.func.drop('do_pushes') s:drop() --- ... +-- +-- gh-3859: box.session.push() succeeds even after the connection +-- is closed. +-- +chan_push = fiber.channel() +--- +... +chan_disconnected = fiber.channel() +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +function do_long_and_push() + box.session.on_disconnect(function() chan_disconnected:put(true) end) + chan_push:get() + ok, err = box.session.push(100) + chan_push:put(err) +end; +--- +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +box.schema.func.create('do_long_and_push') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'do_long_and_push') +--- +... +f = fiber.create(function() c:call('do_long_and_push') end) +--- +... c:close() --- ... +chan_disconnected:get() +--- +- true +... +chan_push:put(true) +--- +- true +... +chan_push:get() +--- +- Connection is not established +... +box.schema.func.drop('do_long_and_push') +--- +... diff --git a/test/box/push.test.lua b/test/box/push.test.lua index 893cf0153..514c08b3e 100644 --- a/test/box/push.test.lua +++ b/test/box/push.test.lua @@ -237,4 +237,26 @@ keys box.schema.func.drop('do_push_and_duplicate') box.schema.func.drop('do_pushes') s:drop() + +-- +-- gh-3859: box.session.push() succeeds even after the connection +-- is closed. +-- +chan_push = fiber.channel() +chan_disconnected = fiber.channel() +test_run:cmd("setopt delimiter ';'") +function do_long_and_push() + box.session.on_disconnect(function() chan_disconnected:put(true) end) + chan_push:get() + ok, err = box.session.push(100) + chan_push:put(err) +end; +test_run:cmd("setopt delimiter ''"); +box.schema.func.create('do_long_and_push') +box.schema.user.grant('guest', 'execute', 'function', 'do_long_and_push') +f = fiber.create(function() c:call('do_long_and_push') end) c:close() +chan_disconnected:get() +chan_push:put(true) +chan_push:get() +box.schema.func.drop('do_long_and_push') -- 2.17.2 (Apple Git-113)