Kaynağa Gözat

* 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 5 yıl önce
ebeveyn
işleme
ad29508ef6
1 değiştirilmiş dosya ile 22 ekleme ve 1 silme
  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