summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
authorDavi Arnaut <davi.arnaut@oracle.com>2010-12-15 20:59:21 -0200
committerDavi Arnaut <davi.arnaut@oracle.com>2010-12-15 20:59:21 -0200
commit487f9bb219318ec804659f0fafa5d0e94d587786 (patch)
tree40ac241a8b0dc4aaa69489f0e28b7b759da0511f /sql/sql_class.cc
parenteb5a21dd909b2001235c7b8cf05075ebc170f6ea (diff)
downloadmariadb-git-487f9bb219318ec804659f0fafa5d0e94d587786.tar.gz
Bug#58136: Crash in vio_close at concurrent disconnect and KILL
The problem is a race between a session closing its vio (i.e. after a COM_QUIT) at the same time it is being killed by another thread. This could trigger a assertion in vio_close() as the two threads could end up closing the same vio, at the same time. This could happen due to the implementation of SIGNAL_WITH_VIO_CLOSE, which closes the vio of the thread being killed. The solution is to serialize the close of the Vio under LOCK_thd_data, which protects THD data. No regression test is added as this is essentially a debug issue and the test case would be quite convoluted as we would need to synchronize a session that is being killed -- which is a bit difficult since debug sync points code does not synchronize killed sessions.
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc34
1 files changed, 34 insertions, 0 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 2df7a2c8572..c4aa4ba7efb 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1283,6 +1283,40 @@ void THD::awake(THD::killed_state state_to_set)
DBUG_VOID_RETURN;
}
+
+/**
+ Close the Vio associated this session.
+
+ @remark LOCK_thd_data is taken due to the fact that
+ the Vio might be disassociated concurrently.
+*/
+
+void THD::disconnect()
+{
+ Vio *vio= NULL;
+
+ mysql_mutex_lock(&LOCK_thd_data);
+
+ killed= THD::KILL_CONNECTION;
+
+#ifdef SIGNAL_WITH_VIO_CLOSE
+ /*
+ Since a active vio might might have not been set yet, in
+ any case save a reference to avoid closing a inexistent
+ one or closing the vio twice if there is a active one.
+ */
+ vio= active_vio;
+ close_active_vio();
+#endif
+
+ /* Disconnect even if a active vio is not associated. */
+ if (net.vio != vio)
+ vio_close(net.vio);
+
+ mysql_mutex_unlock(&LOCK_thd_data);
+}
+
+
/*
Remember the location of thread info, the structure needed for
sql_alloc() and the structure for the net buffer