From: Stefan Eissing Date: Thu, 25 Feb 2016 10:27:27 +0000 (+0000) Subject: merging pre_close_connection hook, prep_lingering_close and ap_update_child() additio... X-Git-Tag: 2.4.19~157 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5eb5ad717f3ea95d370abb17828bee4ac67b8d22;p=apache merging pre_close_connection hook, prep_lingering_close and ap_update_child() additions from trunk git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1732275 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 90e56c4300..368830c038 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -461,6 +461,10 @@ * 20120211.54 (2.4.19-dev) Add ap_proxy_buckets_lifetime_transform and * ap_proxy_transfer_between_connections to * mod_proxy.h + * 20120211.55 (2.4.19-dev) Add new ap_update_child_status...() methods, + * add protocol to worker_score in scoreboard.h, + * Add pre_close connection hook and + * ap_prep_lingering_close(). */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -468,7 +472,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 54 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 55 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_connection.h b/include/http_connection.h index 58389a4fb4..8bc009da3b 100644 --- a/include/http_connection.h +++ b/include/http_connection.h @@ -75,6 +75,8 @@ AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c); */ AP_DECLARE(void) ap_lingering_close(conn_rec *c); +AP_DECLARE(int) ap_prep_lingering_close(conn_rec *c); + AP_DECLARE(int) ap_start_lingering_close(conn_rec *c); /* Hooks */ @@ -121,6 +123,18 @@ AP_DECLARE_HOOK(int,pre_connection,(conn_rec *c, void *csd)) */ AP_DECLARE_HOOK(int,process_connection,(conn_rec *c)) +/** + * This hook implements different protocols. Before a connection is closed, + * protocols might have to perform some housekeeping actions, such as + * sending one last goodbye packet. The connection is, unless some other + * error already happened before, still open and operational. + * All pre-close-connection hooks are run until one returns something + * other than ok or decline + * @param c The connection on which the request has been received. + * @return OK or DECLINED + */ +AP_DECLARE_HOOK(int,pre_close_connection,(conn_rec *c)) + /** End Of Connection (EOC) bucket */ AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eoc; diff --git a/include/scoreboard.h b/include/scoreboard.h index 99d6ba7432..d712bd43b4 100644 --- a/include/scoreboard.h +++ b/include/scoreboard.h @@ -115,6 +115,7 @@ struct worker_score { char client[32]; /* Keep 'em small... */ char request[64]; /* We just want an idea... */ char vhost[32]; /* What virtual host is being accessed? */ + char protocol[16]; /* What protocol is used on the connection? */ }; typedef struct { @@ -181,6 +182,10 @@ AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status, request_ AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num, int thread_num, int status, request_rec *r); AP_DECLARE(int) ap_update_child_status_from_conn(ap_sb_handle_t *sbh, int status, conn_rec *c); +AP_DECLARE(int) ap_update_child_status_from_server(ap_sb_handle_t *sbh, int status, + conn_rec *c, server_rec *s); +AP_DECLARE(int) ap_update_child_status_descr(ap_sb_handle_t *sbh, int status, const char *descr); + AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status); AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh); diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c index 9bd4e8aa04..4ff9df1988 100644 --- a/modules/generators/mod_status.c +++ b/modules/generators/mod_status.c @@ -662,7 +662,7 @@ static int status_handler(request_rec *r) #endif "SSReq" "ConnChildSlot" - "ClientVHost" + "ClientProtocolVHost" "Request\n\n", r); for (i = 0; i < server_limit; ++i) { @@ -776,12 +776,14 @@ static int status_handler(request_rec *r) format_byte_out(r, bytes); ap_rputs(")\n", r); ap_rprintf(r, - " %s {%s} [%s]
\n\n", + " %s {%s} (%s) [%s]
\n\n", ap_escape_html(r->pool, ws_record->client), ap_escape_html(r->pool, ap_escape_logitem(r->pool, ws_record->request)), + ap_escape_html(r->pool, + ws_record->protocol), ap_escape_html(r->pool, ws_record->vhost)); } @@ -860,10 +862,12 @@ static int status_handler(request_rec *r) (float)conn_bytes / KBYTE, (float) my_bytes / MBYTE, (float)bytes / MBYTE); - ap_rprintf(r, "%s%s" + ap_rprintf(r, "%s%s%s" "%s\n\n", ap_escape_html(r->pool, ws_record->client), + ap_escape_html(r->pool, + ws_record->protocol), ap_escape_html(r->pool, ws_record->vhost), ap_escape_html(r->pool, diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 381f3e016c..2f85c3fdc1 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -31,6 +31,7 @@ #include "ssl_private.h" #include "mod_ssl.h" #include "util_md5.h" +#include "scoreboard.h" static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); #ifdef HAVE_TLSEXT @@ -2202,6 +2203,7 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) sslcon->server = s; sslcon->cipher_suite = sc->server->auth.cipher_suite; + ap_update_child_status_from_server(c->sbh, SERVER_BUSY_READ, c, s); /* * There is one special filter callback, which is set * very early depending on the base_server's log level. diff --git a/server/connection.c b/server/connection.c index 44a6dbe49a..917e661c4f 100644 --- a/server/connection.c +++ b/server/connection.c @@ -34,12 +34,15 @@ APR_HOOK_STRUCT( APR_HOOK_LINK(create_connection) APR_HOOK_LINK(process_connection) APR_HOOK_LINK(pre_connection) + APR_HOOK_LINK(pre_close_connection) ) AP_IMPLEMENT_HOOK_RUN_FIRST(conn_rec *,create_connection, (apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc), (p, server, csd, conn_id, sbh, alloc), NULL) AP_IMPLEMENT_HOOK_RUN_FIRST(int,process_connection,(conn_rec *c),(c),DECLINED) AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED) +AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_close_connection,(conn_rec *c),(c),OK,DECLINED) + /* * More machine-dependent networking gooo... on some systems, * you've got to be *really* sure that all the packets are acknowledged @@ -92,6 +95,17 @@ AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c) (void)ap_shutdown_conn(c, 1); } +AP_DECLARE(int) ap_prep_lingering_close(conn_rec *c) +{ + /* Give protocol handlers one last chance to raise their voice */ + ap_run_pre_close_connection(c); + + if (c->sbh) { + ap_update_child_status(c->sbh, SERVER_CLOSING, NULL); + } + return 0; +} + /* we now proceed to read from the client until we get EOF, or until * MAX_SECS_TO_LINGER has passed. The reasons for doing this are * documented in a draft: @@ -112,10 +126,10 @@ AP_DECLARE(int) ap_start_lingering_close(conn_rec *c) return 1; } - if (c->sbh) { - ap_update_child_status(c->sbh, SERVER_CLOSING, NULL); + if (ap_prep_lingering_close(c)) { + return 1; } - + #ifdef NO_LINGCLOSE ap_flush_conn(c); /* just close it */ apr_socket_close(csd); diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index 7346cc5173..e76dee3441 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -905,7 +905,8 @@ static int start_lingering_close_nonblocking(event_conn_state_t *cs) conn_rec *c = cs->c; apr_socket_t *csd = cs->pfd.desc.s; - if (c->aborted + if (ap_prep_lingering_close(c) + || c->aborted || ap_shutdown_conn(c, 0) != APR_SUCCESS || c->aborted || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { apr_socket_close(csd); diff --git a/server/scoreboard.c b/server/scoreboard.c index 6d1b3befb4..8040fc6a83 100644 --- a/server/scoreboard.c +++ b/server/scoreboard.c @@ -32,6 +32,7 @@ #include "http_main.h" #include "http_core.h" #include "http_config.h" +#include "http_protocol.h" #include "ap_mpm.h" #include "scoreboard.h" @@ -457,7 +458,9 @@ static int update_child_status_internal(int child_num, int thread_num, int status, conn_rec *c, - request_rec *r) + server_rec *s, + request_rec *r, + const char *descr) { int old_status; worker_score *ws; @@ -466,19 +469,22 @@ static int update_child_status_internal(int child_num, ws = &ap_scoreboard_image->servers[child_num][thread_num]; old_status = ws->status; - ws->status = status; - - ps = &ap_scoreboard_image->parent[child_num]; - - if (status == SERVER_READY - && old_status == SERVER_STARTING) { - ws->thread_num = child_num * thread_limit + thread_num; - ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation); - ps->generation = mpm_generation; + if (status >= 0) { + ws->status = status; + + ps = &ap_scoreboard_image->parent[child_num]; + + if (status == SERVER_READY + && old_status == SERVER_STARTING) { + ws->thread_num = child_num * thread_limit + thread_num; + ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation); + ps->generation = mpm_generation; + } } if (ap_extended_status) { - ws->last_used = apr_time_now(); + const char *val; + if (status == SERVER_READY || status == SERVER_DEAD) { /* * Reset individual counters @@ -489,28 +495,44 @@ static int update_child_status_internal(int child_num, } ws->conn_count = 0; ws->conn_bytes = 0; + ws->last_used = apr_time_now(); } - if (r) { - const char *client = ap_get_remote_host(c, r->per_dir_config, - REMOTE_NOLOOKUP, NULL); - if (!client || !strcmp(client, c->client_ip)) { - apr_cpystrn(ws->client, r->useragent_ip, sizeof(ws->client)); + if (status == SERVER_READY) { + ws->client[0]='\0'; + ws->vhost[0]='\0'; + ws->request[0]='\0'; + ws->protocol[0]='\0'; + } + else { + if (descr) { + apr_cpystrn(ws->request, descr, sizeof(ws->request)); } - else { - apr_cpystrn(ws->client, client, sizeof(ws->client)); + else if (r) { + copy_request(ws->request, sizeof(ws->request), r); } - copy_request(ws->request, sizeof(ws->request), r); - if (r->server) { - apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d", - r->server->server_hostname, - r->connection->local_addr->port); + if (r || c) { + val = ap_get_remote_host(c, r? r->per_dir_config : NULL, + REMOTE_NOLOOKUP, NULL); + if (r && (!val || !strcmp(val, c->client_ip))) { + apr_cpystrn(ws->client, r->useragent_ip, sizeof(ws->client)); + } + else { + apr_cpystrn(ws->client, val, sizeof(ws->client)); + } + } + if (s) { + if (c) { + apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d", + s->server_hostname, c->local_addr->port); + } + else { + apr_cpystrn(ws->vhost, s->server_hostname, sizeof(ws->vhost)); + } + } + if (c) { + val = ap_get_protocol(c); + apr_cpystrn(ws->protocol, val, sizeof(ws->protocol)); } - } - else if (c) { - apr_cpystrn(ws->client, ap_get_remote_host(c, NULL, - REMOTE_NOLOOKUP, NULL), sizeof(ws->client)); - ws->request[0]='\0'; - ws->vhost[0]='\0'; } } @@ -528,7 +550,8 @@ AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num, return update_child_status_internal(child_num, thread_num, status, r ? r->connection : NULL, - r); + r ? r->server : NULL, + r, NULL); } AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status, @@ -540,17 +563,37 @@ AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status, return update_child_status_internal(sbh->child_num, sbh->thread_num, status, r ? r->connection : NULL, - r); + r ? r->server : NULL, + r, NULL); } AP_DECLARE(int) ap_update_child_status_from_conn(ap_sb_handle_t *sbh, int status, - conn_rec *c) + conn_rec *c) +{ + if (!sbh || (sbh->child_num < 0)) + return -1; + + return update_child_status_internal(sbh->child_num, sbh->thread_num, + status, c, NULL, NULL, NULL); +} + +AP_DECLARE(int) ap_update_child_status_from_server(ap_sb_handle_t *sbh, int status, + conn_rec *c, server_rec *s) +{ + if (!sbh || (sbh->child_num < 0)) + return -1; + + return update_child_status_internal(sbh->child_num, sbh->thread_num, + status, c, s, NULL, NULL); +} + +AP_DECLARE(int) ap_update_child_status_descr(ap_sb_handle_t *sbh, int status, const char *descr) { if (!sbh || (sbh->child_num < 0)) return -1; return update_child_status_internal(sbh->child_num, sbh->thread_num, - status, c, NULL); + status, NULL, NULL, NULL, descr); } AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status) @@ -567,10 +610,10 @@ AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status) ws = &ap_scoreboard_image->servers[sbh->child_num][sbh->thread_num]; if (status == START_PREQUEST) { - ws->start_time = apr_time_now(); + ws->start_time = ws->last_used = apr_time_now(); } else if (status == STOP_PREQUEST) { - ws->stop_time = apr_time_now(); + ws->stop_time = ws->last_used = apr_time_now(); } } @@ -605,6 +648,7 @@ AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest, dest->client[sizeof(dest->client) - 1] = '\0'; dest->request[sizeof(dest->request) - 1] = '\0'; dest->vhost[sizeof(dest->vhost) - 1] = '\0'; + dest->protocol[sizeof(dest->protocol) - 1] = '\0'; } AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)