return iostate;
}
+class ReadFunctionGuard
+{
+public:
+ ReadFunctionGuard(bool& inReadFunction) :
+ d_inReadFunctionRef(inReadFunction)
+ {
+ d_inReadFunctionRef = true;
+ }
+ ReadFunctionGuard(ReadFunctionGuard&&) = delete;
+ ReadFunctionGuard(const ReadFunctionGuard&) = delete;
+ ReadFunctionGuard& operator=(ReadFunctionGuard&&) = delete;
+ ReadFunctionGuard& operator=(const ReadFunctionGuard&) = delete;
+ ~ReadFunctionGuard()
+ {
+ d_inReadFunctionRef = false;
+ }
+
+private:
+ bool& d_inReadFunctionRef;
+};
+
void IncomingHTTP2Connection::handleIO()
{
IOState iostate = IOState::Done;
}
}
- if (active() && !d_connectionClosing && (d_state == State::waitingForQuery || d_state == State::idle)) {
+ if (!d_inReadFunction && active() && !d_connectionClosing && (d_state == State::waitingForQuery || d_state == State::idle)) {
do {
iostate = readHTTPData();
- } while (active() && !d_connectionClosing && iostate == IOState::Done);
+ } while (!d_inReadFunction && active() && !d_connectionClosing && iostate == IOState::Done);
}
if (!active()) {
IOState IncomingHTTP2Connection::readHTTPData()
{
+ if (d_inReadFunction) {
+ return IOState::Done;
+ }
+ ReadFunctionGuard readGuard(d_inReadFunction);
+
IOState newState = IOState::Done;
size_t got = 0;
if (d_in.size() < s_initialReceiveBufferSize) {
/* Whether we have data that we want to write to the socket,
but the socket is full. */
bool d_pendingWrite{false};
+ /* Whether we are currently inside the readHTTPData function,
+ which is not reentrant and could be called from itself via
+ the nghttp2 callbacks */
+ bool d_inReadFunction{false};
};
class NGHTTP2Headers