Procházet zdrojové kódy

* Fix issue 828: Make sure the thread specific storage is available during mg_set_handler_type() call.
It is used in cases when hook deletion is made during an active HTTP request.
In such situations the thread which tries to delete the hook is put to sleep and it's TLS structure is used to maintain the wait queue during the sleep (next_waiting_thread field of mg_workerTLS structure)

eugene před 5 roky
rodič
revize
ad29508ef6
1 změnil soubory, kde provedl 22 přidání a 1 odebrání
  1. 22 1
      src/civetweb.c

+ 22 - 1
src/civetweb.c

@@ -2692,6 +2692,7 @@ struct mg_context {
 	unsigned int
 	    cfg_worker_threads;      /* The number of configured worker threads. */
 	pthread_t *worker_threadids; /* The worker thread IDs */
+    unsigned long starter_thread_idx; /* thread index which called mg_start */
 
 /* Connection to thread dispatching */
 #if defined(ALTERNATIVE_QUEUE)
@@ -13467,6 +13468,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 {
 	struct mg_handler_info *tmp_rh, **lastref;
 	size_t urilen = strlen(uri);
+    struct mg_workerTLS tls;
 
 	if (handler_type == WEBSOCKET_HANDLER) {
 		DEBUG_ASSERT(handler == NULL);
@@ -13523,6 +13525,14 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		return;
 	}
 
+    tls.is_master = -1;
+    tls.thread_idx = phys_ctx->starter_thread_idx;
+#if defined(_WIN32)
+    tls.pthread_cond_helper_mutex = NULL;
+#endif
+
+    pthread_setspecific(sTlsKey, &tls);
+
 	mg_lock_context(phys_ctx);
 
 	/* first try to find an existing handler */
@@ -13564,6 +13574,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 					mg_free(tmp_rh);
 				}
 				mg_unlock_context(phys_ctx);
+                pthread_setspecific(sTlsKey, NULL);
 				return;
 			}
 		}
@@ -13574,6 +13585,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		/* no handler to set, this was a remove request to a non-existing
 		 * handler */
 		mg_unlock_context(phys_ctx);
+        pthread_setspecific(sTlsKey, NULL);
 		return;
 	}
 
@@ -13586,6 +13598,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		mg_cry_ctx_internal(phys_ctx,
 		                    "%s",
 		                    "Cannot create new request handler struct, OOM");
+        pthread_setspecific(sTlsKey, NULL);
 		return;
 	}
 	tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx);
@@ -13595,6 +13608,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		mg_cry_ctx_internal(phys_ctx,
 		                    "%s",
 		                    "Cannot create new request handler struct, OOM");
+        pthread_setspecific(sTlsKey, NULL);
 		return;
 	}
 	tmp_rh->uri_len = urilen;
@@ -13604,6 +13618,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 			mg_unlock_context(phys_ctx);
 			mg_free(tmp_rh);
 			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount mutex");
+            pthread_setspecific(sTlsKey, NULL);
 			return;
 		}
 		if (0 != pthread_cond_init(&tmp_rh->refcount_cond, NULL)) {
@@ -13611,6 +13626,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 			pthread_mutex_destroy(&tmp_rh->refcount_mutex);
 			mg_free(tmp_rh);
 			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount cond");
+            pthread_setspecific(sTlsKey, NULL);
 			return;
 		}
 		tmp_rh->refcount = 0;
@@ -13630,6 +13646,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 
 	*lastref = tmp_rh;
 	mg_unlock_context(phys_ctx);
+    pthread_setspecific(sTlsKey, NULL);
 }
 
 
@@ -18915,8 +18932,12 @@ static
 	ctx->dd.auth_nonce_mask =
 	    (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
 
+    /* Save started thread index to reuse in other external API calls
+     * For the sake of thread synchronization all non-civetweb threads 
+     * can be considered as single external thread */
+    ctx->starter_thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
 	tls.is_master = -1; /* Thread calling mg_start */
-	tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
+    tls.thread_idx = ctx->starter_thread_idx;
 #if defined(_WIN32)
 	tls.pthread_cond_helper_mutex = NULL;
 #endif