Skip to content

Commit a12998a

Browse files
nshylocker
authored andcommitted
iproto: fix assertion on dropping of a new connection
We need to handle case of dropping new connection. When net_send_greeting() is executed the connection can be closed due to iproto_drop_connections() call. Note that in the test the Tarantool crashes for another reason. Due to access after sleep to the connection that is destroyed so its memory is poisoned. Yet we visit net_send_greeting() too in the test with patch so original issue is verified too. We also need to test that such a connection is closed. This will be done in EE version. Closes tarantool#9717 NO_DOC=bugfix
1 parent d592f26 commit a12998a

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## bugfix/core
2+
3+
* Fixed a crash on dropping a just accepted connection (gh-9717).

src/box/iproto.cc

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,8 @@ struct iproto_connection
918918
* connection.
919919
*/
920920
struct cmsg cancel_msg;
921+
/** Set if connection is accepted in TX. */
922+
bool is_established;
921923
};
922924

923925
/** Returns a string suitable for logging. */
@@ -1663,6 +1665,7 @@ iproto_connection_new(struct iproto_thread *iproto_thread)
16631665
con->session = NULL;
16641666
con->is_in_replication = false;
16651667
con->is_drop_pending = false;
1668+
con->is_established = false;
16661669
rlist_create(&con->in_stop_list);
16671670
rlist_create(&con->tx.inprogress);
16681671
rlist_add_entry(&iproto_thread->connections, con, in_connections);
@@ -3329,6 +3332,11 @@ net_send_greeting(struct cmsg *m)
33293332
{
33303333
struct iproto_msg *msg = (struct iproto_msg *) m;
33313334
struct iproto_connection *con = msg->connection;
3335+
if (con->is_drop_pending) {
3336+
iproto_connection_close(con);
3337+
iproto_msg_delete(msg);
3338+
return;
3339+
}
33323340
if (msg->close_connection) {
33333341
struct obuf *out = msg->wpos.obuf;
33343342
int64_t nwr = iostream_writev(&con->io, out->iov,
@@ -3345,6 +3353,7 @@ net_send_greeting(struct cmsg *m)
33453353
iproto_msg_delete(msg);
33463354
return;
33473355
}
3356+
con->is_established = true;
33483357
con->wend = msg->wpos;
33493358
/*
33503359
* Connect is synchronous, so no one could have been
@@ -3988,9 +3997,16 @@ iproto_do_cfg_f(struct cbus_call_msg *m)
39883997
* cannot close them as usual. Anyway we cancel
39893998
* replication fibers as well and close connection
39903999
* after replication is breaked.
4000+
*
4001+
* Do not close connection that is not yet
4002+
* established. Otherwise session
4003+
* on_connect/on_disconnect callbacks may be
4004+
* executed in reverse order in case of yields
4005+
* in on_connect callbacks.
39914006
*/
39924007
if (!con->is_in_replication &&
3993-
con->state == IPROTO_CONNECTION_ALIVE)
4008+
con->state == IPROTO_CONNECTION_ALIVE &&
4009+
con->is_established)
39944010
iproto_connection_close(con);
39954011
/*
39964012
* Do not wait deletion of connection that called

test/box-luatest/shutdown_test.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local server = require('luatest.server')
22
local utils = require('luatest.utils')
3+
local justrun = require('test.justrun')
34
local fio = require('fio')
45
local popen = require('popen')
56
local fiber = require('fiber')
@@ -74,6 +75,33 @@ g_crash.test_shutdown_during_snapshot_on_signal = function(cg)
7475
t.assert_equals(status.exit_code, 0)
7576
end
7677

78+
-- Test shutdown when new iproto connection is accepted but
79+
-- not yet fully established.
80+
g_crash.test_shutdown_during_new_connection = function(cg)
81+
local script = [[
82+
local net = require('net.box')
83+
local fiber = require('fiber')
84+
85+
local sock = 'unix/:./iproto.sock'
86+
box.cfg{listen = sock}
87+
local cond = fiber.cond()
88+
local in_trigger = false
89+
box.session.on_connect(function()
90+
in_trigger = true
91+
cond:signal()
92+
fiber.sleep(1)
93+
end)
94+
net.connect(sock, {wait_connected = false})
95+
while not in_trigger do
96+
cond:wait()
97+
end
98+
os.exit()
99+
]]
100+
local result = justrun.tarantool(cg.workdir, {}, {'-e', script},
101+
{nojson = true, quote_args = true})
102+
t.assert_equals(result.exit_code, 0)
103+
end
104+
77105
local g = t.group()
78106

79107
g.before_each(function(cg)

0 commit comments

Comments
 (0)