Ver código fonte

* 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 anos atrás
pai
commit
ad29508ef6
1 arquivos alterados com 22 adições e 1 exclusões
  1. 22 1
      src/civetweb.c

+ 22 - 1
src/civetweb.c

@@ -2692,6 +2692,7 @@ struct mg_context {
 	unsigned int
 	unsigned int
 	    cfg_worker_threads;      /* The number of configured worker threads. */
 	    cfg_worker_threads;      /* The number of configured worker threads. */
 	pthread_t *worker_threadids; /* The worker thread IDs */
 	pthread_t *worker_threadids; /* The worker thread IDs */
+    unsigned long starter_thread_idx; /* thread index which called mg_start */
 
 
 /* Connection to thread dispatching */
 /* Connection to thread dispatching */
 #if defined(ALTERNATIVE_QUEUE)
 #if defined(ALTERNATIVE_QUEUE)
@@ -13467,6 +13468,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 {
 {
 	struct mg_handler_info *tmp_rh, **lastref;
 	struct mg_handler_info *tmp_rh, **lastref;
 	size_t urilen = strlen(uri);
 	size_t urilen = strlen(uri);
+    struct mg_workerTLS tls;
 
 
 	if (handler_type == WEBSOCKET_HANDLER) {
 	if (handler_type == WEBSOCKET_HANDLER) {
 		DEBUG_ASSERT(handler == NULL);
 		DEBUG_ASSERT(handler == NULL);
@@ -13523,6 +13525,14 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		return;
 		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);
 	mg_lock_context(phys_ctx);
 
 
 	/* first try to find an existing handler */
 	/* 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_free(tmp_rh);
 				}
 				}
 				mg_unlock_context(phys_ctx);
 				mg_unlock_context(phys_ctx);
+                pthread_setspecific(sTlsKey, NULL);
 				return;
 				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
 		/* no handler to set, this was a remove request to a non-existing
 		 * handler */
 		 * handler */
 		mg_unlock_context(phys_ctx);
 		mg_unlock_context(phys_ctx);
+        pthread_setspecific(sTlsKey, NULL);
 		return;
 		return;
 	}
 	}
 
 
@@ -13586,6 +13598,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		mg_cry_ctx_internal(phys_ctx,
 		mg_cry_ctx_internal(phys_ctx,
 		                    "%s",
 		                    "%s",
 		                    "Cannot create new request handler struct, OOM");
 		                    "Cannot create new request handler struct, OOM");
+        pthread_setspecific(sTlsKey, NULL);
 		return;
 		return;
 	}
 	}
 	tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx);
 	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,
 		mg_cry_ctx_internal(phys_ctx,
 		                    "%s",
 		                    "%s",
 		                    "Cannot create new request handler struct, OOM");
 		                    "Cannot create new request handler struct, OOM");
+        pthread_setspecific(sTlsKey, NULL);
 		return;
 		return;
 	}
 	}
 	tmp_rh->uri_len = urilen;
 	tmp_rh->uri_len = urilen;
@@ -13604,6 +13618,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 			mg_unlock_context(phys_ctx);
 			mg_unlock_context(phys_ctx);
 			mg_free(tmp_rh);
 			mg_free(tmp_rh);
 			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount mutex");
 			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount mutex");
+            pthread_setspecific(sTlsKey, NULL);
 			return;
 			return;
 		}
 		}
 		if (0 != pthread_cond_init(&tmp_rh->refcount_cond, NULL)) {
 		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);
 			pthread_mutex_destroy(&tmp_rh->refcount_mutex);
 			mg_free(tmp_rh);
 			mg_free(tmp_rh);
 			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount cond");
 			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount cond");
+            pthread_setspecific(sTlsKey, NULL);
 			return;
 			return;
 		}
 		}
 		tmp_rh->refcount = 0;
 		tmp_rh->refcount = 0;
@@ -13630,6 +13646,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 
 
 	*lastref = tmp_rh;
 	*lastref = tmp_rh;
 	mg_unlock_context(phys_ctx);
 	mg_unlock_context(phys_ctx);
+    pthread_setspecific(sTlsKey, NULL);
 }
 }
 
 
 
 
@@ -18915,8 +18932,12 @@ static
 	ctx->dd.auth_nonce_mask =
 	ctx->dd.auth_nonce_mask =
 	    (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
 	    (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.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)
 #if defined(_WIN32)
 	tls.pthread_cond_helper_mutex = NULL;
 	tls.pthread_cond_helper_mutex = NULL;
 #endif
 #endif