timeout_reset(conn->to_idle);
}
+bool http_server_connection_shut_down(struct http_server_connection *conn)
+{
+ if (conn->request_queue_head == NULL ||
+ conn->request_queue_head->state == HTTP_SERVER_REQUEST_STATE_NEW) {
+ http_server_connection_close(&conn, "Server shutting down");
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void http_server_connection_ready(struct http_server_connection *conn)
{
struct stat st;
http_server_connection_pipeline_is_full(struct http_server_connection *conn)
{
return (conn->request_queue_count >=
- conn->server->set.max_pipelined_requests);
+ conn->server->set.max_pipelined_requests ||
+ conn->server->shutting_down);
}
static void
http_server_connection_pipeline_handle_full(
struct http_server_connection *conn)
{
- http_server_connection_debug(conn,
- "Pipeline full (%u requests pending; %u maximum)",
- conn->request_queue_count,
- conn->server->set.max_pipelined_requests);
+ if (conn->server->shutting_down) {
+ http_server_connection_debug(conn,
+ "Pipeline full (%u requests pending; server shutting down)",
+ conn->request_queue_count);
+ } else {
+ http_server_connection_debug(conn,
+ "Pipeline full (%u requests pending; %u maximum)",
+ conn->request_queue_count,
+ conn->server->set.max_pipelined_requests);
+ }
http_server_connection_input_halt(conn);
}
bool cont;
int ret;
+ if (conn->server->shutting_down) {
+ if (!http_server_connection_shut_down(conn))
+ http_server_connection_pipeline_handle_full(conn);
+ return;
+ }
+
i_assert(!conn->in_req_callback);
i_assert(!conn->input_broken && conn->incoming_payload == NULL);
i_assert(!conn->close_indicated);
/* accept more requests if possible */
if (conn->incoming_payload == NULL &&
- conn->request_queue_count < conn->server->set.max_pipelined_requests) {
+ conn->request_queue_count < conn->server->set.max_pipelined_requests &&
+ !conn->server->shutting_down) {
http_server_connection_input_resume(conn);
return 1;
}
}
}
+ if (conn->server->shutting_down &&
+ http_server_connection_shut_down(conn))
+ return 1;
+
if (!http_server_connection_pipeline_is_full(conn)) {
http_server_connection_input_resume(conn);
if (pipeline_was_full && conn->conn.io != NULL)
in_port_t port;
const char *name;
+ i_assert(!server->shutting_down);
+
conn = i_new(struct http_server_connection, 1);
conn->refcount = 1;
conn->id = id++;
http_server_connection_switch_ioloop(conn);
}
}
+
+void http_server_shut_down(struct http_server *server)
+{
+ struct connection *_conn, *_next;
+
+ server->shutting_down = TRUE;
+
+ for (_conn = server->conn_list->connections;
+ _conn != NULL; _conn = _next) {
+ struct http_server_connection *conn =
+ (struct http_server_connection *)_conn;
+
+ _next = _conn->next;
+ (void)http_server_connection_shut_down(conn);
+ }
+}