Open
Description
I'm running websocket++ with asio_no_tls config in a single thread which immediately forwads requests to other threads. They don't iteract with the server in any way except calling send(), which according to the docs is thread safe by default. I've recently compiled the server with -fsanitize=thread and a data race condition was detected in the library when one of the clients disconnected. It points to send() and terminate() in connection_impl.hpp:
template <typename config>
lib::error_code connection<config>::send(typename config::message_type::ptr msg)
{
...
{
scoped_lock_type lock(m_connection_state_lock);
if (m_state != session::state::open) { // <------ here
return error::make_error_code(error::invalid_state);
}
}
template <typename config>
void connection<config>::terminate(lib::error_code const & ec) {
...
if (m_state == session::state::connecting) {
m_state = session::state::closed;
tstat = failed;
// Log fail result here before socket is shut down and we can't get
// the remote address, etc anymore
if (m_ec != error::http_connection_ended) {
log_fail_result();
}
} else if (m_state != session::state::closed) {
m_state = session::state::closed; <------ and here
tstat = closed;
} else {
m_alog.write(log::alevel::devel,
"terminate called on connection that was already terminated");
return;
}
Here's the complete log: http://pastebin.com/2Adyapd1
// Edit: I've just noticed that right above the mentioned code in terminate(), there's a "// TODO: does any of this need a mutex?". So erm... looks like it does.