diff options
author | Davi Arnaut <davi.arnaut@oracle.com> | 2010-12-15 20:59:21 -0200 |
---|---|---|
committer | Davi Arnaut <davi.arnaut@oracle.com> | 2010-12-15 20:59:21 -0200 |
commit | 487f9bb219318ec804659f0fafa5d0e94d587786 (patch) | |
tree | 40ac241a8b0dc4aaa69489f0e28b7b759da0511f /sql/sql_class.cc | |
parent | eb5a21dd909b2001235c7b8cf05075ebc170f6ea (diff) | |
download | mariadb-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.cc | 34 |
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 |