Browse Source

Merge pull request #871 from civetweb/wip-ssl-error-queue

Fix about SSL context and locking
bel2125 5 years ago
parent
commit
4aeff60615
4 changed files with 171 additions and 273 deletions
  1. 23 2
      examples/embedded_c/embedded_c.c
  2. 6 3
      include/civetweb.h
  3. 1 1
      src/CivetServer.cpp
  4. 141 267
      src/civetweb.c

+ 23 - 2
examples/embedded_c/embedded_c.c

@@ -854,6 +854,16 @@ WebSocketCloseHandler(const struct mg_connection *conn, void *cbdata)
 	ASSERT(client->state >= 1);
 	ASSERT(client->state >= 1);
 
 
 	mg_lock_context(ctx);
 	mg_lock_context(ctx);
+	while (client->state == 3) {
+		/* "inform" state, wait a while */
+		mg_unlock_context(ctx);
+#ifdef _WIN32
+		Sleep(1);
+#else
+		usleep(1000);
+#endif
+		mg_lock_context(ctx);
+	}
 	client->state = 0;
 	client->state = 0;
 	client->conn = NULL;
 	client->conn = NULL;
 	mg_unlock_context(ctx);
 	mg_unlock_context(ctx);
@@ -874,16 +884,27 @@ InformWebsockets(struct mg_context *ctx)
 	sprintf(text, "%lu", ++cnt);
 	sprintf(text, "%lu", ++cnt);
 	textlen = strlen(text);
 	textlen = strlen(text);
 
 
-	mg_lock_context(ctx);
 	for (i = 0; i < MAX_WS_CLIENTS; i++) {
 	for (i = 0; i < MAX_WS_CLIENTS; i++) {
+		int inform = 0;
+
+		mg_lock_context(ctx);
 		if (ws_clients[i].state == 2) {
 		if (ws_clients[i].state == 2) {
+			/* move to "inform" state */
+			ws_clients[i].state = 3;
+			inform = 1;
+		}
+		mg_unlock_context(ctx);
+
+		if (inform) {
 			mg_websocket_write(ws_clients[i].conn,
 			mg_websocket_write(ws_clients[i].conn,
 			                   MG_WEBSOCKET_OPCODE_TEXT,
 			                   MG_WEBSOCKET_OPCODE_TEXT,
 			                   text,
 			                   text,
 			                   textlen);
 			                   textlen);
+			mg_lock_context(ctx);
+			ws_clients[i].state = 2;
+			mg_unlock_context(ctx);
 		}
 		}
 	}
 	}
-	mg_unlock_context(ctx);
 }
 }
 #endif
 #endif
 
 

+ 6 - 3
include/civetweb.h

@@ -503,7 +503,8 @@ typedef int (*mg_request_handler)(struct mg_connection *conn, void *cbdata);
 /* mg_set_request_handler
 /* mg_set_request_handler
 
 
    Sets or removes a URI mapping for a request handler.
    Sets or removes a URI mapping for a request handler.
-   This function uses mg_lock_context internally.
+   This function waits until a removing/updating handler becomes unused, so
+   do not call from the handler itself.
 
 
    URI's are ordered and prefixed URI's are supported. For example,
    URI's are ordered and prefixed URI's are supported. For example,
    consider two URIs: /a/b and /a
    consider two URIs: /a/b and /a
@@ -858,7 +859,8 @@ CIVETWEB_API int mg_websocket_client_write(struct mg_connection *conn,
    with websockets only.
    with websockets only.
    Invoke this before mg_write or mg_printf when communicating with a
    Invoke this before mg_write or mg_printf when communicating with a
    websocket if your code has server-initiated communication as well as
    websocket if your code has server-initiated communication as well as
-   communication in direct response to a message. */
+   communication in direct response to a message.
+   Do not acquire this lock while holding mg_lock_context(). */
 CIVETWEB_API void mg_lock_connection(struct mg_connection *conn);
 CIVETWEB_API void mg_lock_connection(struct mg_connection *conn);
 CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn);
 CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn);
 
 
@@ -870,7 +872,8 @@ CIVETWEB_API void mg_unlock_connection(struct mg_connection *conn);
 
 
 
 
 /* Lock server context.  This lock may be used to protect resources
 /* Lock server context.  This lock may be used to protect resources
-   that are shared between different connection/worker threads. */
+   that are shared between different connection/worker threads.
+   If the given context is not server, these functions do nothing. */
 CIVETWEB_API void mg_lock_context(struct mg_context *ctx);
 CIVETWEB_API void mg_lock_context(struct mg_context *ctx);
 CIVETWEB_API void mg_unlock_context(struct mg_context *ctx);
 CIVETWEB_API void mg_unlock_context(struct mg_context *ctx);
 
 

+ 1 - 1
src/CivetServer.cpp

@@ -464,9 +464,9 @@ CivetServer::getParam(struct mg_connection *conn,
 	assert(me != NULL);
 	assert(me != NULL);
 	mg_lock_context(me->context);
 	mg_lock_context(me->context);
 	CivetConnection &conobj = me->connections[conn];
 	CivetConnection &conobj = me->connections[conn];
-	mg_lock_connection(conn);
 	mg_unlock_context(me->context);
 	mg_unlock_context(me->context);
 
 
+	mg_lock_connection(conn);
 	if (conobj.postData.empty()) {
 	if (conobj.postData.empty()) {
 		// check if there is a request body
 		// check if there is a request body
 		for (;;) {
 		for (;;) {

+ 141 - 267
src/civetweb.c

@@ -2013,8 +2013,6 @@ typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl,
 	SSL_CTX_callback_ctrl(ctx,                                                 \
 	SSL_CTX_callback_ctrl(ctx,                                                 \
 	                      SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                   \
 	                      SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                   \
 	                      (void (*)(void))cb)
 	                      (void (*)(void))cb)
-#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)                            \
-	SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg)
 #define SSL_set_tlsext_host_name(ctx, arg)                                     \
 #define SSL_set_tlsext_host_name(ctx, arg)                                     \
 	SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
 	SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
 
 
@@ -2213,8 +2211,6 @@ typedef int (*tSSL_next_protos_advertised_cb)(SSL *ssl,
 	SSL_CTX_callback_ctrl(ctx,                                                 \
 	SSL_CTX_callback_ctrl(ctx,                                                 \
 	                      SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                   \
 	                      SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,                   \
 	                      (void (*)(void))cb)
 	                      (void (*)(void))cb)
-#define SSL_CTX_set_tlsext_servername_arg(ctx, arg)                            \
-	SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG, 0, (void *)arg)
 #define SSL_set_tlsext_host_name(ctx, arg)                                     \
 #define SSL_set_tlsext_host_name(ctx, arg)                                     \
 	SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
 	SSL_ctrl(ctx, SSL_CTRL_SET_TLSEXT_HOSTNAME, 0, (void *)arg)
 
 
@@ -2701,9 +2697,7 @@ struct mg_handler_info {
 	/* Handler for http/https or authorization requests. */
 	/* Handler for http/https or authorization requests. */
 	mg_request_handler handler;
 	mg_request_handler handler;
 	unsigned int refcount;
 	unsigned int refcount;
-	pthread_mutex_t refcount_mutex; /* Protects refcount */
-	pthread_cond_t
-	    refcount_cond; /* Signaled when handler refcount is decremented */
+	int removing;
 
 
 	/* Handler for ws/wss (websocket) requests. */
 	/* Handler for ws/wss (websocket) requests. */
 	mg_websocket_connect_handler connect_handler;
 	mg_websocket_connect_handler connect_handler;
@@ -2737,6 +2731,7 @@ struct mg_domain_context {
 	SSL_CTX *ssl_ctx;                 /* SSL context */
 	SSL_CTX *ssl_ctx;                 /* SSL context */
 	char *config[NUM_OPTIONS];        /* Civetweb configuration parameters */
 	char *config[NUM_OPTIONS];        /* Civetweb configuration parameters */
 	struct mg_handler_info *handlers; /* linked list of uri handlers */
 	struct mg_handler_info *handlers; /* linked list of uri handlers */
+	int64_t ssl_cert_last_mtime;
 
 
 	/* Server nonce */
 	/* Server nonce */
 	uint64_t auth_nonce_mask;  /* Mask for all nonce values */
 	uint64_t auth_nonce_mask;  /* Mask for all nonce values */
@@ -2819,7 +2814,7 @@ struct mg_context {
 
 
 	/* Thread related */
 	/* Thread related */
 	stop_flag_t stop_flag;        /* Should we stop event loop */
 	stop_flag_t stop_flag;        /* Should we stop event loop */
-	pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
+	pthread_mutex_t thread_mutex; /* Protects client_socks or queue */
 
 
 	pthread_t masterthreadid; /* The master thread ID */
 	pthread_t masterthreadid; /* The master thread ID */
 	unsigned int
 	unsigned int
@@ -2867,7 +2862,9 @@ struct mg_context {
 #endif
 #endif
 
 
 	/* Server nonce */
 	/* Server nonce */
-	pthread_mutex_t nonce_mutex; /* Protects nonce_count */
+	pthread_mutex_t nonce_mutex; /* Protects ssl_ctx, handlers,
+	                              * ssl_cert_last_mtime, nonce_count, and
+	                              * next (linked list) */
 
 
 	/* Server callbacks */
 	/* Server callbacks */
 	struct mg_callbacks callbacks; /* User-defined callback function */
 	struct mg_callbacks callbacks; /* User-defined callback function */
@@ -6470,6 +6467,7 @@ push_inner(struct mg_context *ctx,
 
 
 #if !defined(NO_SSL)
 #if !defined(NO_SSL)
 		if (ssl != NULL) {
 		if (ssl != NULL) {
+			ERR_clear_error();
 			n = SSL_write(ssl, buf, len);
 			n = SSL_write(ssl, buf, len);
 			if (n <= 0) {
 			if (n <= 0) {
 				err = SSL_get_error(ssl, n);
 				err = SSL_get_error(ssl, n);
@@ -6480,8 +6478,10 @@ push_inner(struct mg_context *ctx,
 					n = 0;
 					n = 0;
 				} else {
 				} else {
 					DEBUG_TRACE("SSL_write() failed, error %d", err);
 					DEBUG_TRACE("SSL_write() failed, error %d", err);
+					ERR_clear_error();
 					return -2;
 					return -2;
 				}
 				}
+				ERR_clear_error();
 			} else {
 			} else {
 				err = 0;
 				err = 0;
 			}
 			}
@@ -6633,9 +6633,6 @@ pull_inner(FILE *fp,
 #else
 #else
 	typedef size_t len_t;
 	typedef size_t len_t;
 #endif
 #endif
-#if !defined(NO_SSL)
-	int ssl_pending;
-#endif
 
 
 	/* We need an additional wait loop around this, because in some cases
 	/* We need an additional wait loop around this, because in some cases
 	 * with TLSwe may get data from the socket but not from SSL_read.
 	 * with TLSwe may get data from the socket but not from SSL_read.
@@ -6660,49 +6657,34 @@ pull_inner(FILE *fp,
 		}
 		}
 
 
 #if !defined(NO_SSL)
 #if !defined(NO_SSL)
-	} else if ((conn->ssl != NULL)
-	           && ((ssl_pending = SSL_pending(conn->ssl)) > 0)) {
-		/* We already know there is no more data buffered in conn->buf
-		 * but there is more available in the SSL layer. So don't poll
-		 * conn->client.sock yet. */
-		if (ssl_pending > len) {
-			ssl_pending = len;
-		}
-		nread = SSL_read(conn->ssl, buf, ssl_pending);
-		if (nread <= 0) {
-			err = SSL_get_error(conn->ssl, nread);
-			if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
-				err = ERRNO;
-			} else if ((err == SSL_ERROR_WANT_READ)
-			           || (err == SSL_ERROR_WANT_WRITE)) {
-				nread = 0;
-			} else {
-				/* All errors should return -2 */
-				DEBUG_TRACE("SSL_read() failed, error %d", err);
-				return -2;
-			}
-
-			ERR_clear_error();
-		} else {
-			err = 0;
-		}
-
 	} else if (conn->ssl != NULL) {
 	} else if (conn->ssl != NULL) {
-
+		int ssl_pending;
 		struct mg_pollfd pfd[1];
 		struct mg_pollfd pfd[1];
 		int pollres;
 		int pollres;
 
 
-		pfd[0].fd = conn->client.sock;
-		pfd[0].events = POLLIN;
-		pollres = mg_poll(pfd,
-		                  1,
-		                  (int)(timeout * 1000.0),
-		                  &(conn->phys_ctx->stop_flag));
-		if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) {
-			return -2;
+		if ((ssl_pending = SSL_pending(conn->ssl)) > 0) {
+			/* We already know there is no more data buffered in conn->buf
+			 * but there is more available in the SSL layer. So don't poll
+			 * conn->client.sock yet. */
+			if (ssl_pending > len) {
+				ssl_pending = len;
+			}
+			pollres = 1;
+		} else {
+			pfd[0].fd = conn->client.sock;
+			pfd[0].events = POLLIN;
+			pollres = mg_poll(pfd,
+			                  1,
+			                  (int)(timeout * 1000.0),
+			                  &(conn->phys_ctx->stop_flag));
+			if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) {
+				return -2;
+			}
 		}
 		}
 		if (pollres > 0) {
 		if (pollres > 0) {
-			nread = SSL_read(conn->ssl, buf, len);
+			ERR_clear_error();
+			nread = SSL_read(conn->ssl, buf,
+			                 (ssl_pending > 0) ? ssl_pending : len);
 			if (nread <= 0) {
 			if (nread <= 0) {
 				err = SSL_get_error(conn->ssl, nread);
 				err = SSL_get_error(conn->ssl, nread);
 				if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
 				if ((err == SSL_ERROR_SYSCALL) && (nread == -1)) {
@@ -6711,13 +6693,15 @@ pull_inner(FILE *fp,
 				           || (err == SSL_ERROR_WANT_WRITE)) {
 				           || (err == SSL_ERROR_WANT_WRITE)) {
 					nread = 0;
 					nread = 0;
 				} else {
 				} else {
+					/* All errors should return -2 */
 					DEBUG_TRACE("SSL_read() failed, error %d", err);
 					DEBUG_TRACE("SSL_read() failed, error %d", err);
+					ERR_clear_error();
 					return -2;
 					return -2;
 				}
 				}
+				ERR_clear_error();
 			} else {
 			} else {
 				err = 0;
 				err = 0;
 			}
 			}
-			ERR_clear_error();
 		} else if (pollres < 0) {
 		} else if (pollres < 0) {
 			/* Error */
 			/* Error */
 			return -2;
 			return -2;
@@ -9053,10 +9037,10 @@ send_authorization_request(struct mg_connection *conn, const char *realm)
 		realm = conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
 		realm = conn->dom_ctx->config[AUTHENTICATION_DOMAIN];
 	}
 	}
 
 
-	(void)pthread_mutex_lock(&conn->phys_ctx->nonce_mutex);
+	mg_lock_context(conn->phys_ctx);
 	nonce += conn->dom_ctx->nonce_count;
 	nonce += conn->dom_ctx->nonce_count;
 	++conn->dom_ctx->nonce_count;
 	++conn->dom_ctx->nonce_count;
-	(void)pthread_mutex_unlock(&conn->phys_ctx->nonce_mutex);
+	mg_unlock_context(conn->phys_ctx);
 
 
 	nonce ^= conn->dom_ctx->auth_nonce_mask;
 	nonce ^= conn->dom_ctx->auth_nonce_mask;
 	conn->status_code = 401;
 	conn->status_code = 401;
@@ -12592,7 +12576,7 @@ mg_unlock_connection(struct mg_connection *conn)
 void
 void
 mg_lock_context(struct mg_context *ctx)
 mg_lock_context(struct mg_context *ctx)
 {
 {
-	if (ctx) {
+	if (ctx && (ctx->context_type == CONTEXT_SERVER)) {
 		(void)pthread_mutex_lock(&ctx->nonce_mutex);
 		(void)pthread_mutex_lock(&ctx->nonce_mutex);
 	}
 	}
 }
 }
@@ -12600,7 +12584,7 @@ mg_lock_context(struct mg_context *ctx)
 void
 void
 mg_unlock_context(struct mg_context *ctx)
 mg_unlock_context(struct mg_context *ctx)
 {
 {
-	if (ctx) {
+	if (ctx && (ctx->context_type == CONTEXT_SERVER)) {
 		(void)pthread_mutex_unlock(&ctx->nonce_mutex);
 		(void)pthread_mutex_unlock(&ctx->nonce_mutex);
 	}
 	}
 }
 }
@@ -13653,7 +13637,9 @@ alloc_get_host(struct mg_connection *conn)
 					conn->dom_ctx = dom;
 					conn->dom_ctx = dom;
 					break;
 					break;
 				}
 				}
+				mg_lock_context(conn->phys_ctx);
 				dom = dom->next;
 				dom = dom->next;
+				mg_unlock_context(conn->phys_ctx);
 			}
 			}
 
 
 			DEBUG_TRACE("HTTP Host: %s", host);
 			DEBUG_TRACE("HTTP Host: %s", host);
@@ -13722,37 +13708,6 @@ redirect_to_https_port(struct mg_connection *conn, int ssl_index)
 
 
 
 
 static void
 static void
-handler_info_acquire(struct mg_handler_info *handler_info)
-{
-	pthread_mutex_lock(&handler_info->refcount_mutex);
-	handler_info->refcount++;
-	pthread_mutex_unlock(&handler_info->refcount_mutex);
-}
-
-
-static void
-handler_info_release(struct mg_handler_info *handler_info)
-{
-	pthread_mutex_lock(&handler_info->refcount_mutex);
-	handler_info->refcount--;
-	pthread_cond_signal(&handler_info->refcount_cond);
-	pthread_mutex_unlock(&handler_info->refcount_mutex);
-}
-
-
-static void
-handler_info_wait_unused(struct mg_handler_info *handler_info)
-{
-	pthread_mutex_lock(&handler_info->refcount_mutex);
-	while (handler_info->refcount) {
-		pthread_cond_wait(&handler_info->refcount_cond,
-		                  &handler_info->refcount_mutex);
-	}
-	pthread_mutex_unlock(&handler_info->refcount_mutex);
-}
-
-
-static void
 mg_set_handler_type(struct mg_context *phys_ctx,
 mg_set_handler_type(struct mg_context *phys_ctx,
                     struct mg_domain_context *dom_ctx,
                     struct mg_domain_context *dom_ctx,
                     const char *uri,
                     const char *uri,
@@ -13769,8 +13724,6 @@ 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;
-	int is_tls_set = 0;
 
 
 	if (handler_type == WEBSOCKET_HANDLER) {
 	if (handler_type == WEBSOCKET_HANDLER) {
 		DEBUG_ASSERT(handler == NULL);
 		DEBUG_ASSERT(handler == NULL);
@@ -13827,35 +13780,25 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		return;
 		return;
 	}
 	}
 
 
-	/* Internal callbacks have their contexts set
-	 * if called from non-related thread, context must be set
-	 * since internal function assumes it exists.
-	 * For an example see how handler_info_wait_unused()
-	 * waits for reference to become zero
-	 */
-	if (NULL == pthread_getspecific(sTlsKey)) {
-		is_tls_set = 1;
-		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 */
-	lastref = &(dom_ctx->handlers);
-	for (tmp_rh = dom_ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
-		if (tmp_rh->handler_type == handler_type) {
-			if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
+	do {
+		lastref = &(dom_ctx->handlers);
+		for (tmp_rh = dom_ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
+			if (tmp_rh->handler_type == handler_type
+			    && (urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
 				if (!is_delete_request) {
 				if (!is_delete_request) {
 					/* update existing handler */
 					/* update existing handler */
 					if (handler_type == REQUEST_HANDLER) {
 					if (handler_type == REQUEST_HANDLER) {
 						/* Wait for end of use before updating */
 						/* Wait for end of use before updating */
-						handler_info_wait_unused(tmp_rh);
-
+						if (tmp_rh->refcount) {
+							mg_unlock_context(phys_ctx);
+							mg_sleep(1);
+							mg_lock_context(phys_ctx);
+							/* tmp_rh might have been freed, search again. */
+							break;
+						}
 						/* Ok, the handler is no more use -> Update it */
 						/* Ok, the handler is no more use -> Update it */
 						tmp_rh->handler = handler;
 						tmp_rh->handler = handler;
 					} else if (handler_type == WEBSOCKET_HANDLER) {
 					} else if (handler_type == WEBSOCKET_HANDLER) {
@@ -13872,35 +13815,31 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 					/* remove existing handler */
 					/* remove existing handler */
 					if (handler_type == REQUEST_HANDLER) {
 					if (handler_type == REQUEST_HANDLER) {
 						/* Wait for end of use before removing */
 						/* Wait for end of use before removing */
-						handler_info_wait_unused(tmp_rh);
-
-						/* Ok, the handler is no more used -> Destroy
-						 * resources
-						 */
-						pthread_cond_destroy(&tmp_rh->refcount_cond);
-						pthread_mutex_destroy(&tmp_rh->refcount_mutex);
+						if (tmp_rh->refcount) {
+							tmp_rh->removing = 1;
+							mg_unlock_context(phys_ctx);
+							mg_sleep(1);
+							mg_lock_context(phys_ctx);
+							/* tmp_rh might have been freed, search again. */
+							break;
+						}
+						/* Ok, the handler is no more used */
 					}
 					}
 					*lastref = tmp_rh->next;
 					*lastref = tmp_rh->next;
 					mg_free(tmp_rh->uri);
 					mg_free(tmp_rh->uri);
 					mg_free(tmp_rh);
 					mg_free(tmp_rh);
 				}
 				}
 				mg_unlock_context(phys_ctx);
 				mg_unlock_context(phys_ctx);
-				if (is_tls_set) {
-					pthread_setspecific(sTlsKey, NULL);
-				}
 				return;
 				return;
 			}
 			}
+			lastref = &(tmp_rh->next);
 		}
 		}
-		lastref = &(tmp_rh->next);
-	}
+	} while (tmp_rh != NULL);
 
 
 	if (is_delete_request) {
 	if (is_delete_request) {
 		/* 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);
-		if (is_tls_set) {
-			pthread_setspecific(sTlsKey, NULL);
-		}
 		return;
 		return;
 	}
 	}
 
 
@@ -13913,9 +13852,6 @@ 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");
-		if (is_tls_set) {
-			pthread_setspecific(sTlsKey, NULL);
-		}
 		return;
 		return;
 	}
 	}
 	tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx);
 	tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx);
@@ -13925,34 +13861,12 @@ 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");
-		if (is_tls_set) {
-			pthread_setspecific(sTlsKey, NULL);
-		}
 		return;
 		return;
 	}
 	}
 	tmp_rh->uri_len = urilen;
 	tmp_rh->uri_len = urilen;
 	if (handler_type == REQUEST_HANDLER) {
 	if (handler_type == REQUEST_HANDLER) {
-		/* Init refcount mutex and condition */
-		if (0 != pthread_mutex_init(&tmp_rh->refcount_mutex, NULL)) {
-			mg_unlock_context(phys_ctx);
-			mg_free(tmp_rh);
-			mg_cry_ctx_internal(phys_ctx, "%s", "Cannot init refcount mutex");
-			if (is_tls_set) {
-				pthread_setspecific(sTlsKey, NULL);
-			}
-			return;
-		}
-		if (0 != pthread_cond_init(&tmp_rh->refcount_cond, NULL)) {
-			mg_unlock_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");
-			if (is_tls_set) {
-				pthread_setspecific(sTlsKey, NULL);
-			}
-			return;
-		}
 		tmp_rh->refcount = 0;
 		tmp_rh->refcount = 0;
+		tmp_rh->removing = 0;
 		tmp_rh->handler = handler;
 		tmp_rh->handler = handler;
 	} else if (handler_type == WEBSOCKET_HANDLER) {
 	} else if (handler_type == WEBSOCKET_HANDLER) {
 		tmp_rh->subprotocols = subprotocols;
 		tmp_rh->subprotocols = subprotocols;
@@ -13969,9 +13883,6 @@ 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);
-	if (is_tls_set) {
-		pthread_setspecific(sTlsKey, NULL);
-	}
 }
 }
 
 
 
 
@@ -14087,6 +13998,7 @@ get_request_handler(struct mg_connection *conn,
 		const char *uri = request_info->local_uri;
 		const char *uri = request_info->local_uri;
 		size_t urilen = strlen(uri);
 		size_t urilen = strlen(uri);
 		struct mg_handler_info *tmp_rh;
 		struct mg_handler_info *tmp_rh;
+		int step, matched;
 
 
 		if (!conn || !conn->phys_ctx || !conn->dom_ctx) {
 		if (!conn || !conn->phys_ctx || !conn->dom_ctx) {
 			return 0;
 			return 0;
@@ -14094,64 +14006,29 @@ get_request_handler(struct mg_connection *conn,
 
 
 		mg_lock_context(conn->phys_ctx);
 		mg_lock_context(conn->phys_ctx);
 
 
-		/* first try for an exact match */
-		for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
-		     tmp_rh = tmp_rh->next) {
-			if (tmp_rh->handler_type == handler_type) {
-				if ((urilen == tmp_rh->uri_len) && !strcmp(tmp_rh->uri, uri)) {
-					if (handler_type == WEBSOCKET_HANDLER) {
-						*subprotocols = tmp_rh->subprotocols;
-						*connect_handler = tmp_rh->connect_handler;
-						*ready_handler = tmp_rh->ready_handler;
-						*data_handler = tmp_rh->data_handler;
-						*close_handler = tmp_rh->close_handler;
-					} else if (handler_type == REQUEST_HANDLER) {
-						*handler = tmp_rh->handler;
-						/* Acquire handler and give it back */
-						handler_info_acquire(tmp_rh);
-						*handler_info = tmp_rh;
-					} else { /* AUTH_HANDLER */
-						*auth_handler = tmp_rh->auth_handler;
-					}
-					*cbdata = tmp_rh->cbdata;
-					mg_unlock_context(conn->phys_ctx);
-					return 1;
+		for (step = 0; step < 3; step++) {
+			for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
+			     tmp_rh = tmp_rh->next) {
+				if (tmp_rh->handler_type != handler_type) {
+					continue;
 				}
 				}
-			}
-		}
-
-		/* next try for a partial match, we will accept uri/something */
-		for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
-		     tmp_rh = tmp_rh->next) {
-			if (tmp_rh->handler_type == handler_type) {
-				if ((tmp_rh->uri_len < urilen) && (uri[tmp_rh->uri_len] == '/')
-				    && (memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0)) {
-					if (handler_type == WEBSOCKET_HANDLER) {
-						*subprotocols = tmp_rh->subprotocols;
-						*connect_handler = tmp_rh->connect_handler;
-						*ready_handler = tmp_rh->ready_handler;
-						*data_handler = tmp_rh->data_handler;
-						*close_handler = tmp_rh->close_handler;
-					} else if (handler_type == REQUEST_HANDLER) {
-						*handler = tmp_rh->handler;
-						/* Acquire handler and give it back */
-						handler_info_acquire(tmp_rh);
-						*handler_info = tmp_rh;
-					} else { /* AUTH_HANDLER */
-						*auth_handler = tmp_rh->auth_handler;
-					}
-					*cbdata = tmp_rh->cbdata;
-					mg_unlock_context(conn->phys_ctx);
-					return 1;
+				if (step == 0) {
+					/* first try for an exact match */
+					matched = (tmp_rh->uri_len == urilen)
+					           && (strcmp(tmp_rh->uri, uri) == 0);
+				} else if (step == 1) {
+					/* next try for a partial match, we will accept
+					   uri/something */
+					matched = (tmp_rh->uri_len < urilen)
+					           && (uri[tmp_rh->uri_len] == '/')
+					           && (memcmp(tmp_rh->uri, uri,
+					                      tmp_rh->uri_len) == 0);
+				} else {
+					/* finally try for pattern match */
+					matched = match_prefix(tmp_rh->uri,
+					                       tmp_rh->uri_len, uri) > 0;
 				}
 				}
-			}
-		}
-
-		/* finally try for pattern match */
-		for (tmp_rh = conn->dom_ctx->handlers; tmp_rh != NULL;
-		     tmp_rh = tmp_rh->next) {
-			if (tmp_rh->handler_type == handler_type) {
-				if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
+				if (matched) {
 					if (handler_type == WEBSOCKET_HANDLER) {
 					if (handler_type == WEBSOCKET_HANDLER) {
 						*subprotocols = tmp_rh->subprotocols;
 						*subprotocols = tmp_rh->subprotocols;
 						*connect_handler = tmp_rh->connect_handler;
 						*connect_handler = tmp_rh->connect_handler;
@@ -14159,9 +14036,14 @@ get_request_handler(struct mg_connection *conn,
 						*data_handler = tmp_rh->data_handler;
 						*data_handler = tmp_rh->data_handler;
 						*close_handler = tmp_rh->close_handler;
 						*close_handler = tmp_rh->close_handler;
 					} else if (handler_type == REQUEST_HANDLER) {
 					} else if (handler_type == REQUEST_HANDLER) {
+						if (tmp_rh->removing) {
+							/* Treat as none found */
+							step = 2;
+							break;
+						}
 						*handler = tmp_rh->handler;
 						*handler = tmp_rh->handler;
 						/* Acquire handler and give it back */
 						/* Acquire handler and give it back */
-						handler_info_acquire(tmp_rh);
+						tmp_rh->refcount++;
 						*handler_info = tmp_rh;
 						*handler_info = tmp_rh;
 					} else { /* AUTH_HANDLER */
 					} else { /* AUTH_HANDLER */
 						*auth_handler = tmp_rh->auth_handler;
 						*auth_handler = tmp_rh->auth_handler;
@@ -14525,7 +14407,9 @@ handle_request(struct mg_connection *conn)
 			i = callback_handler(conn, callback_data);
 			i = callback_handler(conn, callback_data);
 
 
 			/* Callback handler will not be used anymore. Release it */
 			/* Callback handler will not be used anymore. Release it */
-			handler_info_release(handler_info);
+			mg_lock_context(conn->phys_ctx);
+			handler_info->refcount--;
+			mg_unlock_context(conn->phys_ctx);
 
 
 			if (i > 0) {
 			if (i > 0) {
 				/* Do nothing, callback has served the request. Store
 				/* Do nothing, callback has served the request. Store
@@ -15612,12 +15496,8 @@ static const char *ssl_error(void);
 static int
 static int
 refresh_trust(struct mg_connection *conn)
 refresh_trust(struct mg_connection *conn)
 {
 {
-	static int reload_lock = 0;
-	static long int data_check = 0;
-	volatile int *p_reload_lock = (volatile int *)&reload_lock;
-
 	struct stat cert_buf;
 	struct stat cert_buf;
-	long int t;
+	int64_t t = 0;
 	const char *pem;
 	const char *pem;
 	const char *chain;
 	const char *chain;
 	int should_verify_peer;
 	int should_verify_peer;
@@ -15636,13 +15516,13 @@ refresh_trust(struct mg_connection *conn)
 		chain = NULL;
 		chain = NULL;
 	}
 	}
 
 
-	t = data_check;
 	if (stat(pem, &cert_buf) != -1) {
 	if (stat(pem, &cert_buf) != -1) {
-		t = (long int)cert_buf.st_mtime;
+		t = (int64_t)cert_buf.st_mtime;
 	}
 	}
 
 
-	if (data_check != t) {
-		data_check = t;
+	mg_lock_context(conn->phys_ctx);
+	if ((t != 0) && (conn->dom_ctx->ssl_cert_last_mtime != t)) {
+		conn->dom_ctx->ssl_cert_last_mtime = t;
 
 
 		should_verify_peer = 0;
 		should_verify_peer = 0;
 		if (conn->dom_ctx->config[SSL_DO_VERIFY_PEER] != NULL) {
 		if (conn->dom_ctx->config[SSL_DO_VERIFY_PEER] != NULL) {
@@ -15663,6 +15543,7 @@ refresh_trust(struct mg_connection *conn)
 			                                  ca_file,
 			                                  ca_file,
 			                                  ca_path)
 			                                  ca_path)
 			    != 1) {
 			    != 1) {
+				mg_unlock_context(conn->phys_ctx);
 				mg_cry_ctx_internal(
 				mg_cry_ctx_internal(
 				    conn->phys_ctx,
 				    conn->phys_ctx,
 				    "SSL_CTX_load_verify_locations error: %s "
 				    "SSL_CTX_load_verify_locations error: %s "
@@ -15675,18 +15556,13 @@ refresh_trust(struct mg_connection *conn)
 			}
 			}
 		}
 		}
 
 
-		if (1 == mg_atomic_inc(p_reload_lock)) {
-			if (ssl_use_pem_file(conn->phys_ctx, conn->dom_ctx, pem, chain)
-			    == 0) {
-				return 0;
-			}
-			*p_reload_lock = 0;
+		if (ssl_use_pem_file(conn->phys_ctx, conn->dom_ctx, pem, chain)
+		    == 0) {
+			mg_unlock_context(conn->phys_ctx);
+			return 0;
 		}
 		}
 	}
 	}
-	/* lock while cert is reloading */
-	while (*p_reload_lock) {
-		sleep(1);
-	}
+	mg_unlock_context(conn->phys_ctx);
 
 
 	return 1;
 	return 1;
 }
 }
@@ -15698,9 +15574,7 @@ static pthread_mutex_t *ssl_mutexes;
 
 
 static int
 static int
 sslize(struct mg_connection *conn,
 sslize(struct mg_connection *conn,
-       SSL_CTX *s,
        int (*func)(SSL *),
        int (*func)(SSL *),
-       stop_flag_t *stop_flag,
        const struct mg_client_options *client_options)
        const struct mg_client_options *client_options)
 {
 {
 	int ret, err;
 	int ret, err;
@@ -15723,16 +15597,19 @@ sslize(struct mg_connection *conn,
 		}
 		}
 	}
 	}
 
 
-	conn->ssl = SSL_new(s);
+	mg_lock_context(conn->phys_ctx);
+	conn->ssl = SSL_new(conn->dom_ctx->ssl_ctx);
+	mg_unlock_context(conn->phys_ctx);
 	if (conn->ssl == NULL) {
 	if (conn->ssl == NULL) {
+		mg_cry_internal(conn, "sslize error: %s", ssl_error());
+		OPENSSL_REMOVE_THREAD_STATE();
 		return 0;
 		return 0;
 	}
 	}
 	SSL_set_app_data(conn->ssl, (char *)conn);
 	SSL_set_app_data(conn->ssl, (char *)conn);
 
 
 	ret = SSL_set_fd(conn->ssl, conn->client.sock);
 	ret = SSL_set_fd(conn->ssl, conn->client.sock);
 	if (ret != 1) {
 	if (ret != 1) {
-		err = SSL_get_error(conn->ssl, ret);
-		mg_cry_internal(conn, "SSL error %i, destroying SSL context", err);
+		mg_cry_internal(conn, "sslize error: %s", ssl_error());
 		SSL_free(conn->ssl);
 		SSL_free(conn->ssl);
 		conn->ssl = NULL;
 		conn->ssl = NULL;
 		OPENSSL_REMOVE_THREAD_STATE();
 		OPENSSL_REMOVE_THREAD_STATE();
@@ -15759,6 +15636,8 @@ sslize(struct mg_connection *conn,
 	 * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html
 	 * see https://www.openssl.org/docs/manmaster/ssl/SSL_get_error.html
 	 * Here "func" could be SSL_connect or SSL_accept. */
 	 * Here "func" could be SSL_connect or SSL_accept. */
 	for (i = 0; i <= timeout; i += 50) {
 	for (i = 0; i <= timeout; i += 50) {
+		ERR_clear_error();
+		/* conn->dom_ctx may be changed here (see ssl_servername_callback) */
 		ret = func(conn->ssl);
 		ret = func(conn->ssl);
 		if (ret != 1) {
 		if (ret != 1) {
 			err = SSL_get_error(conn->ssl, ret);
 			err = SSL_get_error(conn->ssl, ret);
@@ -15766,7 +15645,7 @@ sslize(struct mg_connection *conn,
 			    || (err == SSL_ERROR_WANT_ACCEPT)
 			    || (err == SSL_ERROR_WANT_ACCEPT)
 			    || (err == SSL_ERROR_WANT_READ) || (err == SSL_ERROR_WANT_WRITE)
 			    || (err == SSL_ERROR_WANT_READ) || (err == SSL_ERROR_WANT_WRITE)
 			    || (err == SSL_ERROR_WANT_X509_LOOKUP)) {
 			    || (err == SSL_ERROR_WANT_X509_LOOKUP)) {
-				if (!STOP_FLAG_IS_ZERO(&*stop_flag)) {
+				if (!STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) {
 					/* Don't wait if the server is going to be stopped. */
 					/* Don't wait if the server is going to be stopped. */
 					break;
 					break;
 				}
 				}
@@ -15784,7 +15663,8 @@ sslize(struct mg_connection *conn,
 					              || (err == SSL_ERROR_WANT_WRITE))
 					              || (err == SSL_ERROR_WANT_WRITE))
 					                 ? POLLOUT
 					                 ? POLLOUT
 					                 : POLLIN;
 					                 : POLLIN;
-					pollres = mg_poll(&pfd, 1, 50, stop_flag);
+					pollres = mg_poll(&pfd, 1, 50,
+					                  &(conn->phys_ctx->stop_flag));
 					if (pollres < 0) {
 					if (pollres < 0) {
 						/* Break if error occured (-1)
 						/* Break if error occured (-1)
 						 * or server shutdown (-2) */
 						 * or server shutdown (-2) */
@@ -15794,8 +15674,7 @@ sslize(struct mg_connection *conn,
 
 
 			} else if (err == SSL_ERROR_SYSCALL) {
 			} else if (err == SSL_ERROR_SYSCALL) {
 				/* This is an IO error. Look at errno. */
 				/* This is an IO error. Look at errno. */
-				err = errno;
-				mg_cry_internal(conn, "SSL syscall error %i", err);
+				mg_cry_internal(conn, "SSL syscall error %i", ERRNO);
 				break;
 				break;
 
 
 			} else {
 			} else {
@@ -15803,13 +15682,13 @@ sslize(struct mg_connection *conn,
 				mg_cry_internal(conn, "sslize error: %s", ssl_error());
 				mg_cry_internal(conn, "sslize error: %s", ssl_error());
 				break;
 				break;
 			}
 			}
-			ERR_clear_error();
 
 
 		} else {
 		} else {
 			/* success */
 			/* success */
 			break;
 			break;
 		}
 		}
 	}
 	}
+	ERR_clear_error();
 
 
 	if (ret != 1) {
 	if (ret != 1) {
 		SSL_free(conn->ssl);
 		SSL_free(conn->ssl);
@@ -16327,9 +16206,6 @@ ssl_info_callback(const SSL *ssl, int what, int ret)
 static int
 static int
 ssl_servername_callback(SSL *ssl, int *ad, void *arg)
 ssl_servername_callback(SSL *ssl, int *ad, void *arg)
 {
 {
-	struct mg_context *ctx = (struct mg_context *)arg;
-	struct mg_domain_context *dom = ((ctx != NULL) ? &(ctx->dd) : NULL);
-
 #if defined(GCC_DIAGNOSTIC)
 #if defined(GCC_DIAGNOSTIC)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wcast-align"
 #pragma GCC diagnostic ignored "-Wcast-align"
@@ -16345,11 +16221,13 @@ ssl_servername_callback(SSL *ssl, int *ad, void *arg)
 	const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
 	const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
 
 
 	(void)ad;
 	(void)ad;
+	(void)arg;
 
 
-	if ((ctx == NULL) || (conn->phys_ctx == ctx)) {
-		DEBUG_TRACE("%s", "internal error - assertion failed");
+	if ((conn == NULL) || (conn->phys_ctx == NULL)) {
+		DEBUG_ASSERT(0);
 		return SSL_TLSEXT_ERR_NOACK;
 		return SSL_TLSEXT_ERR_NOACK;
 	}
 	}
+	conn->dom_ctx = &(conn->phys_ctx->dd);
 
 
 	/* Old clients (Win XP) will not support SNI. Then, there
 	/* Old clients (Win XP) will not support SNI. Then, there
 	 * is no server name available in the request - we can
 	 * is no server name available in the request - we can
@@ -16359,31 +16237,36 @@ ssl_servername_callback(SSL *ssl, int *ad, void *arg)
 	 */
 	 */
 	if ((servername == NULL) || (*servername == 0)) {
 	if ((servername == NULL) || (*servername == 0)) {
 		DEBUG_TRACE("%s", "SSL connection not supporting SNI");
 		DEBUG_TRACE("%s", "SSL connection not supporting SNI");
-		conn->dom_ctx = &(ctx->dd);
+		mg_lock_context(conn->phys_ctx);
 		SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx);
 		SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx);
+		mg_unlock_context(conn->phys_ctx);
 		return SSL_TLSEXT_ERR_NOACK;
 		return SSL_TLSEXT_ERR_NOACK;
 	}
 	}
 
 
 	DEBUG_TRACE("TLS connection to host %s", servername);
 	DEBUG_TRACE("TLS connection to host %s", servername);
 
 
-	while (dom) {
-		if (!mg_strcasecmp(servername, dom->config[AUTHENTICATION_DOMAIN])) {
-
+	while (conn->dom_ctx) {
+		if (!mg_strcasecmp(servername,
+		                   conn->dom_ctx->config[AUTHENTICATION_DOMAIN])) {
 			/* Found matching domain */
 			/* Found matching domain */
 			DEBUG_TRACE("TLS domain %s found",
 			DEBUG_TRACE("TLS domain %s found",
-			            dom->config[AUTHENTICATION_DOMAIN]);
-			SSL_set_SSL_CTX(ssl, dom->ssl_ctx);
-			conn->dom_ctx = dom;
-			return SSL_TLSEXT_ERR_OK;
+			            conn->dom_ctx->config[AUTHENTICATION_DOMAIN]);
+			break;
 		}
 		}
-		dom = dom->next;
+		mg_lock_context(conn->phys_ctx);
+		conn->dom_ctx = conn->dom_ctx->next;
+		mg_unlock_context(conn->phys_ctx);
 	}
 	}
 
 
-	/* Default domain */
-	DEBUG_TRACE("TLS default domain %s used",
-	            ctx->dd.config[AUTHENTICATION_DOMAIN]);
-	conn->dom_ctx = &(ctx->dd);
+	if (conn->dom_ctx == NULL) {
+		/* Default domain */
+		DEBUG_TRACE("TLS default domain %s used",
+		            conn->phys_ctx->dd.config[AUTHENTICATION_DOMAIN]);
+		conn->dom_ctx = &(conn->phys_ctx->dd);
+	}
+	mg_lock_context(conn->phys_ctx);
 	SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx);
 	SSL_set_SSL_CTX(ssl, conn->dom_ctx->ssl_ctx);
+	mg_unlock_context(conn->phys_ctx);
 	return SSL_TLSEXT_ERR_OK;
 	return SSL_TLSEXT_ERR_OK;
 }
 }
 
 
@@ -16558,7 +16441,6 @@ init_ssl_ctx_impl(struct mg_context *phys_ctx,
 
 
 	SSL_CTX_set_tlsext_servername_callback(dom_ctx->ssl_ctx,
 	SSL_CTX_set_tlsext_servername_callback(dom_ctx->ssl_ctx,
 	                                       ssl_servername_callback);
 	                                       ssl_servername_callback);
-	SSL_CTX_set_tlsext_servername_arg(dom_ctx->ssl_ctx, phys_ctx);
 
 
 	/* If a callback has been specified, call it. */
 	/* If a callback has been specified, call it. */
 	callback_ret = (phys_ctx->callbacks.init_ssl == NULL)
 	callback_ret = (phys_ctx->callbacks.init_ssl == NULL)
@@ -17375,9 +17257,7 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 		}
 		}
 
 
 		if (!sslize(conn,
 		if (!sslize(conn,
-		            conn->dom_ctx->ssl_ctx,
 		            SSL_connect,
 		            SSL_connect,
-		            &(conn->phys_ctx->stop_flag),
 		            client_options)) {
 		            client_options)) {
 			mg_snprintf(NULL,
 			mg_snprintf(NULL,
 			            NULL, /* No truncation check for ebuf */
 			            NULL, /* No truncation check for ebuf */
@@ -18903,9 +18783,7 @@ worker_thread_run(struct mg_connection *conn)
 #if !defined(NO_SSL)
 #if !defined(NO_SSL)
 			/* HTTPS connection */
 			/* HTTPS connection */
 			if (sslize(conn,
 			if (sslize(conn,
-			           conn->dom_ctx->ssl_ctx,
 			           SSL_accept,
 			           SSL_accept,
-			           &(conn->phys_ctx->stop_flag),
 			           NULL)) {
 			           NULL)) {
 				/* conn->dom_ctx is set in get_request */
 				/* conn->dom_ctx is set in get_request */
 
 
@@ -19311,10 +19189,6 @@ free_context(struct mg_context *ctx)
 	while (ctx->dd.handlers) {
 	while (ctx->dd.handlers) {
 		tmp_rh = ctx->dd.handlers;
 		tmp_rh = ctx->dd.handlers;
 		ctx->dd.handlers = tmp_rh->next;
 		ctx->dd.handlers = tmp_rh->next;
-		if (tmp_rh->handler_type == REQUEST_HANDLER) {
-			pthread_cond_destroy(&tmp_rh->refcount_cond);
-			pthread_mutex_destroy(&tmp_rh->refcount_mutex);
-		}
 		mg_free(tmp_rh->uri);
 		mg_free(tmp_rh->uri);
 		mg_free(tmp_rh);
 		mg_free(tmp_rh);
 	}
 	}