mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-12 13:42:10 +02:00
http: prevent race condition between worker thread and I/O thread
This prevents a losing race condition that could prevent the server from reading requests from an HTTP client. A connected socket can either be written to or read from based on the result of GenerateWaitSockets(). That method checks the HTTPRemoteClient flag m_send_ready. If it's `true` the implication is that there is data in the client's send buffer ready to go. Once that data is sent and the buffer is empty, MaybeSendBytesFromBuffer() sets it `false` again. The sad case was when a worker thread calling WriteReply() adds data to the send buffer, but before it sets m_send_ready to `true`, the I/O thread sends that data and empties the buffer. With the buffer unexpectedly empty, WriteReply() sets m_send_ready to `true`. The effect of this is that the socket will stay in "write" mode with nothing to write. With nothing to write, MaybeSendBytesFromBuffer() never sets it back to `false` and the socket is stuck forever.
This commit is contained in:
@@ -483,11 +483,14 @@ public:
|
||||
/// @}
|
||||
|
||||
/**
|
||||
* Set true by worker threads after writing a response to m_send_buffer.
|
||||
* Set false by the HTTPServer I/O thread after flushing m_send_buffer.
|
||||
* Checked in the HTTPServer I/O loop to avoid locking m_send_mutex if there's nothing to send.
|
||||
*/
|
||||
std::atomic_bool m_send_ready{false};
|
||||
* Set true by worker threads after writing a response to m_send_buffer.
|
||||
* Set false by the HTTPServer I/O thread after flushing m_send_buffer.
|
||||
* Checked in the HTTPServer I/O loop to decide whether to poll the socket for
|
||||
* writeability or readability.
|
||||
* Guarded by m_send_mutex so it stays consistent with m_send_buffer's emptiness:
|
||||
* the two must always be updated together under the same lock.
|
||||
*/
|
||||
bool m_send_ready GUARDED_BY(m_send_mutex){false};
|
||||
|
||||
/**
|
||||
* Mutex that serializes the Send() and Recv() calls on `m_sock`. Reading
|
||||
|
||||
Reference in New Issue
Block a user