|  | @@ -9637,9 +9637,8 @@ static unsigned long ssl_id_callback(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	struct mg_workerTLS *tls =
 | 
	
		
			
				|  |  |  	    (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
 | 
	
		
			
				|  |  | -	if (tls == NULL) {
 | 
	
		
			
				|  |  | -		return 0;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	/* Do not check for tls == NULL here. If tls == NULL, something is wrong
 | 
	
		
			
				|  |  | +     * and there is no way to fix it here. In particular, do not return 0. */
 | 
	
		
			
				|  |  |  	return tls->thread_idx;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -11249,6 +11248,8 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  	unsigned int i;
 | 
	
		
			
				|  |  |  	void (*exit_callback)(const struct mg_context *ctx) = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	struct mg_workerTLS tls;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if defined(_WIN32) && !defined(__SYMBIAN32__)
 | 
	
		
			
				|  |  |  	WSADATA data;
 | 
	
		
			
				|  |  |  	WSAStartup(MAKEWORD(2, 2), &data);
 | 
	
	
		
			
				|  | @@ -11280,6 +11281,13 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  		mg_sleep(1);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	tls.is_master = -1;
 | 
	
		
			
				|  |  | +	tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
 | 
	
		
			
				|  |  | +#if defined(_WIN32) && !defined(__SYMBIAN32__)
 | 
	
		
			
				|  |  | +	tls.pthread_cond_helper_mutex = NULL;
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +	pthread_setspecific(sTlsKey, &tls);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	ok = 0 == pthread_mutex_init(&ctx->thread_mutex, NULL);
 | 
	
		
			
				|  |  |  	ok &= 0 == pthread_cond_init(&ctx->thread_cond, NULL);
 | 
	
		
			
				|  |  |  	ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
 | 
	
	
		
			
				|  | @@ -11290,6 +11298,7 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  		 * occur in practice. */
 | 
	
		
			
				|  |  |  		mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
 | 
	
		
			
				|  |  |  		mg_free(ctx);
 | 
	
		
			
				|  |  | +		pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  		return NULL;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -11309,10 +11318,12 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  		if ((idx = get_option_index(name)) == -1) {
 | 
	
		
			
				|  |  |  			mg_cry(fc(ctx), "Invalid option: %s", name);
 | 
	
		
			
				|  |  |  			free_context(ctx);
 | 
	
		
			
				|  |  | +			pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  			return NULL;
 | 
	
		
			
				|  |  |  		} else if ((value = *options++) == NULL) {
 | 
	
		
			
				|  |  |  			mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
 | 
	
		
			
				|  |  |  			free_context(ctx);
 | 
	
		
			
				|  |  | +			pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  			return NULL;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		if (ctx->config[idx] != NULL) {
 | 
	
	
		
			
				|  | @@ -11335,6 +11346,7 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  	if (ctx->config[DOCUMENT_ROOT] != NULL) {
 | 
	
		
			
				|  |  |  		mg_cry(fc(ctx), "%s", "Document root must not be set");
 | 
	
		
			
				|  |  |  		free_context(ctx);
 | 
	
		
			
				|  |  | +		pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  		return NULL;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  #endif
 | 
	
	
		
			
				|  | @@ -11353,6 +11365,7 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  	    !set_acl_option(ctx)) {
 | 
	
		
			
				|  |  |  		free_context(ctx);
 | 
	
		
			
				|  |  | +		pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  		return NULL;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -11367,6 +11380,7 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  	if (workerthreadcount > MAX_WORKER_THREADS) {
 | 
	
		
			
				|  |  |  		mg_cry(fc(ctx), "Too many worker threads");
 | 
	
		
			
				|  |  |  		free_context(ctx);
 | 
	
		
			
				|  |  | +		pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  		return NULL;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -11377,6 +11391,7 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  		if (ctx->workerthreadids == NULL) {
 | 
	
		
			
				|  |  |  			mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
 | 
	
		
			
				|  |  |  			free_context(ctx);
 | 
	
		
			
				|  |  | +			pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  			return NULL;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -11385,6 +11400,7 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  	if (timers_init(ctx) != 0) {
 | 
	
		
			
				|  |  |  		mg_cry(fc(ctx), "Error creating timers");
 | 
	
		
			
				|  |  |  		free_context(ctx);
 | 
	
		
			
				|  |  | +		pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  		return NULL;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  #endif
 | 
	
	
		
			
				|  | @@ -11418,12 +11434,14 @@ struct mg_context *mg_start(const struct mg_callbacks *callbacks,
 | 
	
		
			
				|  |  |  				mg_cry(
 | 
	
		
			
				|  |  |  				    fc(ctx), "Cannot create threads: error %ld", (long)ERRNO);
 | 
	
		
			
				|  |  |  				free_context(ctx);
 | 
	
		
			
				|  |  | +				pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  				return NULL;
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  			break;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	pthread_setspecific(sTlsKey, NULL);
 | 
	
		
			
				|  |  |  	return ctx;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |