in proxygen/lib/http/session/HTTPSession.cpp [1029:1091]
void HTTPSession::onError(HTTPCodec::StreamID streamID,
const HTTPException& error,
bool newTxn) {
DestructorGuard dg(this);
// The codec detected an error in the ingress stream, possibly bad
// syntax, a truncated message, or bad semantics in the frame. If reads
// are paused, queue up the event; otherwise, process it now.
VLOG(4) << "Error on " << *this << ", streamID=" << streamID << ", " << error;
if (ingressError_) {
return;
}
if (!codec_->supportsParallelRequests()) {
// this error should only prevent us from reading/handling more errors
// on serial streams
ingressError_ = true;
setCloseReason(ConnectionCloseReason::SESSION_PARSE_ERROR);
}
if ((streamID == 0) && infoCallback_) {
infoCallback_->onIngressError(*this, kErrorMessage);
}
if (!streamID) {
ingressError_ = true;
onSessionParseError(error);
return;
}
HTTPTransaction* txn = findTransaction(streamID);
if (!txn) {
if (error.hasHttpStatusCode() && streamID != 0) {
// If the error has an HTTP code, then parsing was fine, it just was
// illegal in a higher level way
txn = createTransaction(
streamID, HTTPCodec::NoStream, HTTPCodec::NoExAttributes);
if (infoCallback_) {
infoCallback_->onRequestBegin(*this);
}
if (txn) {
handleErrorDirectly(txn, error);
}
} else if (newTxn) {
onNewTransactionParseError(streamID, error);
} else {
VLOG(4) << *this << " parse error with invalid transaction";
invalidStream(streamID);
}
return;
}
if (!txn->getHandler() &&
txn->getEgressState() == HTTPTransactionEgressSM::State::Start) {
handleErrorDirectly(txn, error);
return;
}
txn->onError(error);
if (!codec_->isReusable() && transactions_.empty()) {
VLOG(4) << *this << "shutdown from onError";
setCloseReason(ConnectionCloseReason::SESSION_PARSE_ERROR);
shutdownTransport(true, true);
}
}