This is an automated email from the ASF dual-hosted git repository.

gsim pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git

commit dfadc670b4b80db44054061d7d9166b2e56681aa
Author: Gordon Sim <g...@redhat.com>
AuthorDate: Mon Apr 8 19:39:54 2019 +0100

    DISPATCH-1315: ensure that the state shared by threads other than the http 
thread cannot be prematurely deleted
---
 src/http-libwebsockets.c | 76 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 60 insertions(+), 16 deletions(-)

diff --git a/src/http-libwebsockets.c b/src/http-libwebsockets.c
index 2da2ff0..db1c10b 100644
--- a/src/http-libwebsockets.c
+++ b/src/http-libwebsockets.c
@@ -98,12 +98,18 @@ typedef struct connection_t {
     struct lws *wsi;
 } connection_t;
 
-typedef struct stats_t {
-    size_t current;
-    bool headers_sent;
+typedef struct stats_request_state_t {
+    bool callback_completed;
+    bool wsi_deleted;
     qdr_global_stats_t stats;
     qd_http_server_t *server;
     struct lws *wsi;
+} stats_request_state_t;
+
+typedef struct stats_t {
+    size_t current;
+    bool headers_sent;
+    stats_request_state_t *context;
 } stats_t;
 
 /* Navigating from WSI pointer to qd objects */
@@ -409,13 +415,33 @@ static void connection_wake(qd_connection_t *qd_conn)
     }
 }
 
+/**
+ * Called on router worker thread
+ */
 static void handle_stats_results(void *context)
 {
-    stats_t* stats = (stats_t*) context;
-    qd_http_server_t *hs = stats->server;
-    if (hs) {
-        work_t w = { W_HANDLE_STATS, stats->wsi };
-        work_push(hs, w);
+    stats_request_state_t* state = (stats_request_state_t*) context;
+    if (state->wsi_deleted) {
+        free(state);
+    } else {
+        qd_http_server_t *hs = state->server;
+        if (hs) {
+            work_t w = { W_HANDLE_STATS, state };
+            work_push(hs, w);
+        }
+    }
+}
+
+/**
+ * Called on http thread
+ */
+static void handle_stats_result_HT(stats_request_state_t* state)
+{
+    if (state->wsi_deleted) {
+        free(state);
+    } else {
+        state->callback_completed = true;
+        lws_callback_on_writable(state->wsi);
     }
 }
 
@@ -499,10 +525,12 @@ static int callback_metrics(struct lws *wsi, enum 
lws_callback_reasons reason,
     switch (reason) {
 
     case LWS_CALLBACK_HTTP: {
-        stats->wsi = wsi;
-        stats->server = hs;
+        stats->context = NEW(stats_request_state_t);
+        ZERO(stats->context);
+        stats->context->wsi = wsi;
+        stats->context->server = hs;
         //request stats from core thread
-        qdr_request_global_stats(hs->core, &stats->stats, 
handle_stats_results, (void*) stats);
+        qdr_request_global_stats(hs->core, &stats->context->stats, 
handle_stats_results, (void*) stats->context);
         return 0;
     }
 
@@ -519,7 +547,7 @@ static int callback_metrics(struct lws *wsi, enum 
lws_callback_reasons reason,
         }
 
         while (stats->current < metrics_length) {
-            if (write_metric(&position, end, &metrics[stats->current], 
&stats->stats)) {
+            if (write_metric(&position, end, &metrics[stats->current], 
&stats->context->stats)) {
                 stats->current++;
                 qd_log(hs->log, QD_LOG_DEBUG, "wrote metric %i of %i", 
stats->current, metrics_length);
             } else {
@@ -541,6 +569,13 @@ static int callback_metrics(struct lws *wsi, enum 
lws_callback_reasons reason,
         return 0;
     }
 
+    case LWS_CALLBACK_CLOSED: {
+        stats->context->wsi_deleted = true;
+        if (stats->context->callback_completed) {
+            free(stats->context);
+        }
+    }
+
     default:
         return 0;
     }
@@ -557,12 +592,14 @@ static int callback_healthz(struct lws *wsi, enum 
lws_callback_reasons reason,
     switch (reason) {
 
     case LWS_CALLBACK_HTTP: {
-        stats->wsi = wsi;
-        stats->server = hs;
+        stats->context = NEW(stats_request_state_t);
+        ZERO(stats->context);
+        stats->context->wsi = wsi;
+        stats->context->server = hs;
         //make dummy request for stats (pass in null ptr); this still 
excercises the
         //path through core thread and back through callback on io thread 
which is
         //a resonable initial liveness check
-        qdr_request_global_stats(hs->core, 0, handle_stats_results, (void*) 
stats);
+        qdr_request_global_stats(hs->core, 0, handle_stats_results, (void*) 
stats->context);
         return 0;
     }
 
@@ -589,6 +626,13 @@ static int callback_healthz(struct lws *wsi, enum 
lws_callback_reasons reason,
         else return 0;
     }
 
+    case LWS_CALLBACK_CLOSED: {
+        stats->context->wsi_deleted = true;
+        if (stats->context->callback_completed) {
+            free(stats->context);
+        }
+    }
+
     default:
         return 0;
     }
@@ -728,7 +772,7 @@ static void* http_thread_run(void* v) {
                 listener_close((qd_http_listener_t*)w.value, hs);
                 break;
             case W_HANDLE_STATS:
-                lws_callback_on_writable((struct lws*) w.value);
+                handle_stats_result_HT((stats_request_state_t*) w.value);
                 break;
             case W_WAKE: {
                 connection_t *c = w.value;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to