]> granicus.if.org Git - apache/commitdiff
new hook pre_close_connection
authorStefan Eissing <icing@apache.org>
Wed, 27 Jan 2016 14:51:53 +0000 (14:51 +0000)
committerStefan Eissing <icing@apache.org>
Wed, 27 Jan 2016 14:51:53 +0000 (14:51 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1727071 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/http_connection.h
server/connection.c
server/mpm/event/event.c

diff --git a/CHANGES b/CHANGES
index f4cbda6a23684bb6858e332a3f8edd1200d38b57..ff45fc222b609b15c5089e18b0cc404f372583ab 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) core: new hook "pre_close_connection" which is run before the lingering
+     close of connections is started. This gives protocol handlers one last
+     chance to use a connection before it goes down.
+     [Stefan Eissing]
+  
   *) mod_filter: Fix AddOutputFilterByType with non-content-level filters.
      PR58856 [Micha Lenk <micha lenk.info>]
  
index 58389a4fb4ea7a010627e8989f11df55ee6cc981..8bc009da3b7fb9f22854d141d9ad5ce24ce19a89 100644 (file)
@@ -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;
 
index ccf685fcd38972cf071cf75dbf99a26dc5a64a37..0959b8550d6e572a12130d3ce07eb1c7953f99f0 100644 (file)
@@ -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;
     }
-
+    
     /* Close the connection, being careful to send out whatever is still
      * in our buffers.  If possible, try to avoid a hard close until the
      * client has ACKed our FIN and/or has stopped sending us data.
index d4f5c68b98eeaab9c19346d57caba69c3491aa9e..21ddd283d9d572e55e6e8bd8cfcba00d50157ae3 100644 (file)
@@ -940,7 +940,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(cs->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);