On Sun, May 8, 2016 at 12:30 PM,  <rj...@apache.org> wrote:
>
> +   * Don't globber scoreboard request info if read_request_line() fails with
> +     a timeout. In that case there's not yet any new useful request info
> +     available.
> +     Noticed via server-status showing request "NULL" after keep-alive
> +     connections timed out.
> +     No CHANGES entry needed, because there's already one for PR 59333.
> +     Sorry for the two patches. The second is better. Both change the same
> +     line, so technically only the second is needed, but merging both keeps
> +     mergeinfo more complete.
> +     trunk patch: http://svn.apache.org/r1742791
> +                  http://svn.apache.org/r1742792

This is to avoid "NULL" instead of blank, right?

ISTM that the request line has already been clobbered (blanked) by the
previous call to ap_update_child_status_from_conn(SERVER_BUSY_READ) in
ap_process_http_[a]sync_connection(), where we already lost the
previous request's line.

That's why I proposed to save the previous request line and host in
the conn_rec, and use them in the scoreboard until a new (real)
request is available (it didn't work as expected because the
scoreboard was clobbered in multiple places before Bill's changes, but
it should work better/easily now).
That would be: when no r is available but c is, use the saved
request-line/host from c; when r is available, use the ones from r and
update them in c.
That way there would be no blank at all (IOW, the scoreboard entry
would be left with the latest request handled on the connection, not a
blank which inevitably ends every connection after keepalive timeout
or close, and shouldn't be taken into account as an empty request
IMHO).

Also, that would be consistent in both MPMs worker and event, whereas
currently event is more likely to show this behaviour, thanks to
queuing (no worker thread used for keepalive handling and hence no
BUSY_READ during that time, no clobbering either).
Thus for mpm_event, we'd need to use
ap_update_child_status_from_conn(SERVER_CLOSING, c) so that the saved
request-line/vhost from the connection get reused when/if a worker
thread handles the lingering close.

How about the attached patch?

Regards,
Yann.
Index: include/httpd.h
===================================================================
--- include/httpd.h	(revision 1742803)
+++ include/httpd.h	(working copy)
@@ -1095,6 +1095,9 @@ typedef enum {
     AP_CONN_KEEPALIVE
 } ap_conn_keepalive_e;
 
+/* AP_SB_*_SIZE needed by conn_rec */
+#include "scoreboard.h"
+
 /**
  * @brief Structure to store things which are per connection
  */
@@ -1217,6 +1220,10 @@ struct conn_rec {
 
     /** The minimum level of filter type to allow setaside buckets */
     int async_filter;
+
+    /** Preserve scoreboard's worker last request infos */
+    char sb_lastrline[AP_SB_RLINE_SIZE];
+    char sb_lastvhost[AP_SB_VHOST_SIZE];
 };
 
 struct conn_slave_rec {
Index: include/scoreboard.h
===================================================================
--- include/scoreboard.h	(revision 1742803)
+++ include/scoreboard.h	(working copy)
@@ -85,6 +85,9 @@ typedef enum {
     SB_SHARED = 2
 } ap_scoreboard_e;
 
+#define AP_SB_RLINE_SIZE 64
+#define AP_SB_VHOST_SIZE 32
+
 /* stuff which is worker specific */
 typedef struct worker_score worker_score;
 struct worker_score {
@@ -113,8 +116,8 @@ struct worker_score {
     struct tms times;
 #endif
     char client[40];            /* Keep 'em small... but large enough to hold an IPv6 address */
-    char request[64];           /* We just want an idea... */
-    char vhost[32];             /* What virtual host is being accessed? */
+    char request[AP_SB_RLINE_SIZE]; /* We just want an idea... */
+    char vhost[AP_SB_VHOST_SIZE];   /* What virtual host is being accessed? */
     char protocol[16];          /* What protocol is used on the connection? */
 };
 
Index: server/connection.c
===================================================================
--- server/connection.c	(revision 1742803)
+++ server/connection.c	(working copy)
@@ -101,7 +101,7 @@ AP_DECLARE(int) ap_prep_lingering_close(conn_rec *
     ap_run_pre_close_connection(c);
     
     if (c->sbh) {
-        ap_update_child_status(c->sbh, SERVER_CLOSING, NULL);
+        ap_update_child_status_from_conn(c->sbh, SERVER_CLOSING, c);
     }
     return 0;
 }
Index: server/scoreboard.c
===================================================================
--- server/scoreboard.c	(revision 1742803)
+++ server/scoreboard.c	(working copy)
@@ -499,9 +499,10 @@ static int update_child_status_internal(int child_
         }
         else if (r) {
             copy_request(ws->request, sizeof(ws->request), r);
+            apr_cpystrn(c->sb_lastrline, ws->request, sizeof(c->sb_lastrline));
         }
         else if (c) {
-            ws->request[0]='\0';
+            apr_cpystrn(ws->request, c->sb_lastrline, sizeof(ws->request));
         }
 
         if (r && r->useragent_ip) {
@@ -522,6 +523,8 @@ static int update_child_status_internal(int child_
             if (c) {
                 apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d",
                              s->server_hostname, c->local_addr->port);
+                apr_cpystrn(c->sb_lastvhost, ws->vhost,
+                            sizeof(c->sb_lastvhost));
             }
             else {
                 apr_cpystrn(ws->vhost, s->server_hostname, sizeof(ws->vhost));
@@ -528,7 +531,7 @@ static int update_child_status_internal(int child_
             }
         }
         else if (c) {
-            ws->vhost[0]='\0';
+            apr_cpystrn(ws->vhost, c->sb_lastvhost, sizeof(ws->vhost));
         }
 
         if (c) {

Reply via email to