shrpx: Added error handling when error_reply() failed

This commit is contained in:
Tatsuhiro Tsujikawa 2012-07-16 23:29:48 +09:00
parent e817995063
commit 0f5a37fa2a
3 changed files with 60 additions and 20 deletions

View File

@ -145,8 +145,11 @@ int htp_hdrs_completecb(http_parser *htp)
if(downstream->get_expect_100_continue()) { if(downstream->get_expect_100_continue()) {
static const char reply_100[] = "HTTP/1.1 100 Continue\r\n\r\n"; static const char reply_100[] = "HTTP/1.1 100 Continue\r\n\r\n";
bufferevent_write(upstream->get_client_handler()->get_bev(), if(bufferevent_write(upstream->get_client_handler()->get_bev(),
reply_100, sizeof(reply_100)-1); reply_100, sizeof(reply_100)-1) != 0) {
LOG(FATAL) << "bufferevent_write() faild";
return -1;
}
} }
int rv = dconn->attach_downstream(downstream); int rv = dconn->attach_downstream(downstream);
@ -154,7 +157,7 @@ int htp_hdrs_completecb(http_parser *htp)
downstream->set_request_state(Downstream::CONNECT_FAIL); downstream->set_request_state(Downstream::CONNECT_FAIL);
downstream->set_downstream_connection(0); downstream->set_downstream_connection(0);
delete dconn; delete dconn;
return 1; return -1;
} else { } else {
downstream->push_request_headers(); downstream->push_request_headers();
downstream->set_request_state(Downstream::HEADER_COMPLETE); downstream->set_request_state(Downstream::HEADER_COMPLETE);
@ -229,7 +232,9 @@ int HttpsUpstream::on_read()
if(htperr == HPE_PAUSED) { if(htperr == HPE_PAUSED) {
if(downstream->get_request_state() == Downstream::CONNECT_FAIL) { if(downstream->get_request_state() == Downstream::CONNECT_FAIL) {
get_client_handler()->set_should_close_after_write(true); get_client_handler()->set_should_close_after_write(true);
error_reply(503); if(error_reply(503) != 0) {
return -1;
}
// Downstream gets deleted after response body is read. // Downstream gets deleted after response body is read.
} else { } else {
assert(downstream->get_request_state() == Downstream::MSG_COMPLETE); assert(downstream->get_request_state() == Downstream::MSG_COMPLETE);
@ -250,7 +255,9 @@ int HttpsUpstream::on_read()
LOG(WARNING) << "Request Header too long:" << current_header_length_ LOG(WARNING) << "Request Header too long:" << current_header_length_
<< " bytes"; << " bytes";
get_client_handler()->set_should_close_after_write(true); get_client_handler()->set_should_close_after_write(true);
error_reply(400); if(error_reply(400) != 0) {
return -1;
}
} else if(downstream->get_output_buffer_full()) { } else if(downstream->get_output_buffer_full()) {
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Downstream output buffer is full"; LOG(INFO) << "Downstream output buffer is full";
@ -265,7 +272,9 @@ int HttpsUpstream::on_read()
<< http_errno_description(htperr); << http_errno_description(htperr);
} }
get_client_handler()->set_should_close_after_write(true); get_client_handler()->set_should_close_after_write(true);
error_reply(400); if(error_reply(400) != 0) {
return -1;
}
} }
return 0; return 0;
} }
@ -359,7 +368,10 @@ void https_downstream_readcb(bufferevent *bev, void *ptr)
} else { } else {
// We did not sent any HTTP response, so sent error // We did not sent any HTTP response, so sent error
// response. Cannot reuse downstream connection in this case. // response. Cannot reuse downstream connection in this case.
upstream->error_reply(502); if(upstream->error_reply(502) != 0) {
delete upstream->get_client_handler();
return;
}
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
upstream->pop_downstream(); upstream->pop_downstream();
delete downstream; delete downstream;
@ -423,7 +435,10 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Treated as downstream error"; LOG(INFO) << "Treated as downstream error";
} }
upstream->error_reply(502); if(upstream->error_reply(502) != 0) {
delete upstream->get_client_handler();
return;
}
} }
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
upstream->pop_downstream(); upstream->pop_downstream();
@ -441,7 +456,10 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
} else { } else {
status = 502; status = 502;
} }
upstream->error_reply(status); if(upstream->error_reply(status) != 0) {
delete upstream->get_client_handler();
return;
}
} }
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
upstream->pop_downstream(); upstream->pop_downstream();
@ -452,7 +470,7 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
} }
} // namespace } // namespace
void HttpsUpstream::error_reply(int status_code) int HttpsUpstream::error_reply(int status_code)
{ {
std::string html = http::create_error_html(status_code); std::string html = http::create_error_html(status_code);
std::stringstream ss; std::stringstream ss;
@ -466,12 +484,16 @@ void HttpsUpstream::error_reply(int status_code)
ss << "\r\n"; ss << "\r\n";
std::string header = ss.str(); std::string header = ss.str();
evbuffer *output = bufferevent_get_output(handler_->get_bev()); evbuffer *output = bufferevent_get_output(handler_->get_bev());
evbuffer_add(output, header.c_str(), header.size()); if(evbuffer_add(output, header.c_str(), header.size()) != 0 ||
evbuffer_add(output, html.c_str(), html.size()); evbuffer_add(output, html.c_str(), html.size()) != 0) {
LOG(FATAL) << "evbuffer_add() failed";
return -1;
}
Downstream *downstream = get_top_downstream(); Downstream *downstream = get_top_downstream();
if(downstream) { if(downstream) {
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
} }
return 0;
} }
bufferevent_data_cb HttpsUpstream::get_downstream_readcb() bufferevent_data_cb HttpsUpstream::get_downstream_readcb()

View File

@ -58,7 +58,7 @@ public:
void pop_downstream(); void pop_downstream();
Downstream* get_top_downstream(); Downstream* get_top_downstream();
Downstream* get_last_downstream(); Downstream* get_last_downstream();
void error_reply(int status_code); int error_reply(int status_code);
void pause_read(IOCtrlReason reason); void pause_read(IOCtrlReason reason);
void resume_read(IOCtrlReason reason); void resume_read(IOCtrlReason reason);

View File

@ -374,7 +374,10 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr)
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) { if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
} else { } else {
upstream->error_reply(downstream, 502); if(upstream->error_reply(downstream, 502) != 0) {
delete upstream->get_client_handler();
return;
}
} }
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
// Clearly, we have to close downstream connection on http parser // Clearly, we have to close downstream connection on http parser
@ -383,7 +386,10 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr)
delete dconn; delete dconn;
dconn = 0; dconn = 0;
} }
upstream->send(); if(upstream->send() != 0) {
delete upstream->get_client_handler();
return;
}
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
} }
} // namespace } // namespace
@ -450,10 +456,16 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
} else { } else {
// If stream was not closed, then we set MSG_COMPLETE and let // If stream was not closed, then we set MSG_COMPLETE and let
// on_stream_close_callback delete downstream. // on_stream_close_callback delete downstream.
upstream->error_reply(downstream, 502); if(upstream->error_reply(downstream, 502) != 0) {
upstream->get_client_handler();
return;
}
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
} }
upstream->send(); if(upstream->send() != 0) {
delete upstream->get_client_handler();
return;
}
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
} }
} else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { } else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
@ -490,11 +502,17 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
} else { } else {
status = 502; status = 502;
} }
upstream->error_reply(downstream, status); if(upstream->error_reply(downstream, status) != 0) {
delete upstream->get_client_handler();
return;
}
} }
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
} }
upstream->send(); if(upstream->send() != 0) {
delete upstream->get_client_handler();
return;
}
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
} }
} }
@ -568,7 +586,7 @@ int SpdyUpstream::error_reply(Downstream *downstream, int status_code)
rv = evbuffer_add(body, html.c_str(), html.size()); rv = evbuffer_add(body, html.c_str(), html.size());
if(rv == -1) { if(rv == -1) {
LOG(FATAL) << "evbuffer_add() failed"; LOG(FATAL) << "evbuffer_add() failed";
DIE(); return -1;
} }
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);