diff --git a/lib/core/service.c b/lib/core/service.c
index 48ad1370833ea3b92da25590807a4698facf530a..be8b4fab4ee15b48fb8902a1b89a1fd38acb351e 100644
--- a/lib/core/service.c
+++ b/lib/core/service.c
@@ -515,10 +515,6 @@ int
 lws_service_flag_pending(struct lws_context *context, int tsi)
 {
 	struct lws_context_per_thread *pt = &context->pt[tsi];
-
-#if defined(LWS_WITH_TLS)
-	struct lws *wsi, *wsi_next;
-#endif
 	int forced = 0;
 
 	lws_pt_lock(pt, __func__);
@@ -548,9 +544,10 @@ lws_service_flag_pending(struct lws_context *context, int tsi)
 	 * service to use up the buffered incoming data, even though their
 	 * network socket may have nothing
 	 */
-	wsi = pt->tls.pending_read_list;
-	while (wsi) {
-		wsi_next = wsi->tls.pending_read_list_next;
+	lws_start_foreach_dll_safe(struct lws_dll_lws *, p, p1,
+				   pt->tls.pending_tls_head.next) {
+		struct lws *wsi = lws_container_of(p, struct lws, tls.pending_tls_list);
+
 		pt->fds[wsi->position_in_fds_table].revents |=
 			pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
 		if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) {
@@ -564,8 +561,7 @@ lws_service_flag_pending(struct lws_context *context, int tsi)
 			__lws_ssl_remove_wsi_from_buffered_list(wsi);
 		}
 
-		wsi = wsi_next;
-	}
+	} lws_end_foreach_dll_safe(p, p1);
 #endif
 
 	lws_pt_unlock(pt);
diff --git a/lib/tls/mbedtls/ssl.c b/lib/tls/mbedtls/ssl.c
index 8e0c6b219a52308a8747a7ce64359ce96db70ae4..b6104715b68bb3bc50e830c0428f92f1010b8e05 100644
--- a/lib/tls/mbedtls/ssl.c
+++ b/lib/tls/mbedtls/ssl.c
@@ -133,23 +133,12 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
 	if (!wsi->tls.ssl)
 		goto bail;
 
-	if (!SSL_pending(wsi->tls.ssl))
-		goto bail;
+	if (SSL_pending(wsi->tls.ssl) &&
+	    lws_dll_is_null(&wsi->tls.pending_tls_list)) {
 
-	if (wsi->tls.pending_read_list_next)
-		return n;
-	if (wsi->tls.pending_read_list_prev)
-		return n;
-	if (pt->tls.pending_read_list == wsi)
-		return n;
-
-	/* add us to the linked list of guys with pending ssl */
-	if (pt->tls.pending_read_list)
-		pt->tls.pending_read_list->tls.pending_read_list_prev = wsi;
-
-	wsi->tls.pending_read_list_next = pt->tls.pending_read_list;
-	wsi->tls.pending_read_list_prev = NULL;
-	pt->tls.pending_read_list = wsi;
+		lws_dll_lws_add_front(&wsi->tls.pending_tls_list,
+				      &pt->tls.pending_tls_head);
+	}
 
 	return n;
 bail:
diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c
index 4afe1d6c30b86a87b0c241a0126315320acff178..63083739a69c5094956d364ceeac0f53fcd98d78 100644
--- a/lib/tls/openssl/openssl-server.c
+++ b/lib/tls/openssl/openssl-server.c
@@ -486,10 +486,19 @@ lws_tls_server_accept(struct lws *wsi)
 			lwsl_notice("%s: client cert CN '%s'\n",
 				    __func__, ir.ns.name);
 		else
-			lwsl_info("%s: couldn't get client cert CN\n", __func__);
+			lwsl_info("%s: no client cert CN\n", __func__);
 
 		lws_openssl_describe_cipher(wsi);
 
+		if (SSL_pending(wsi->tls.ssl) &&
+		    lws_dll_is_null(&wsi->tls.pending_tls_list)) {
+			struct lws_context_per_thread *pt =
+					&wsi->context->pt[(int)wsi->tsi];
+
+			lws_dll_lws_add_front(&wsi->tls.pending_tls_list,
+					      &pt->tls.pending_tls_head);
+		}
+
 		return LWS_SSL_CAPABLE_DONE;
 	}
 
diff --git a/lib/tls/openssl/ssl.c b/lib/tls/openssl/ssl.c
index 0e847238f15dbf26930318cd8534165856185842..8396bb34de82c70f5c06e8588dd869304793aa3b 100644
--- a/lib/tls/openssl/ssl.c
+++ b/lib/tls/openssl/ssl.c
@@ -318,23 +318,12 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
 	if (!wsi->tls.ssl)
 		goto bail;
 
-	if (!SSL_pending(wsi->tls.ssl))
-		goto bail;
+	if (SSL_pending(wsi->tls.ssl) &&
+	    lws_dll_is_null(&wsi->tls.pending_tls_list)) {
 
-	if (wsi->tls.pending_read_list_next)
-		return n;
-	if (wsi->tls.pending_read_list_prev)
-		return n;
-	if (pt->tls.pending_read_list == wsi)
-		return n;
-
-	/* add us to the linked list of guys with pending ssl */
-	if (pt->tls.pending_read_list)
-		pt->tls.pending_read_list->tls.pending_read_list_prev = wsi;
-
-	wsi->tls.pending_read_list_next = pt->tls.pending_read_list;
-	wsi->tls.pending_read_list_prev = NULL;
-	pt->tls.pending_read_list = wsi;
+		lws_dll_lws_add_front(&wsi->tls.pending_tls_list,
+				      &pt->tls.pending_tls_head);
+	}
 
 	return n;
 bail:
diff --git a/lib/tls/private.h b/lib/tls/private.h
index fa1205cee28258a1871f5e706aeb4c149043aec6..4687de7596e77252eb34be3685dce098eaa7e5fc 100644
--- a/lib/tls/private.h
+++ b/lib/tls/private.h
@@ -115,7 +115,7 @@ struct lws_context_tls {
 };
 
 struct lws_pt_tls {
-	struct lws *pending_read_list; /* linked list */
+	struct lws_dll_lws pending_tls_head;
 };
 
 struct lws_tls_ss_pieces;
@@ -149,7 +149,7 @@ struct lws_vhost_tls {
 struct lws_lws_tls {
 	lws_tls_conn *ssl;
 	lws_tls_bio *client_bio;
-	struct lws *pending_read_list_prev, *pending_read_list_next;
+	struct lws_dll_lws pending_tls_list;
 	unsigned int use_ssl;
 	unsigned int redirect_to_https:1;
 };
@@ -280,4 +280,4 @@ lws_ssl_info_callback(const lws_tls_conn *ssl, int where, int ret);
 int
 lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/lib/tls/tls.c b/lib/tls/tls.c
index 8cf39ab175cde72422532ed3ca7150b9973752d6..be08ba93e2d169a5cfc90fa10e17f6c1e64fdb71 100644
--- a/lib/tls/tls.c
+++ b/lib/tls/tls.c
@@ -30,18 +30,18 @@
 int
 lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt)
 {
-	struct lws *wsi, *wsi_next;
 	int ret = 0;
 
-	wsi = pt->tls.pending_read_list;
-	while (wsi && wsi->position_in_fds_table != LWS_NO_FDS_POS) {
-		wsi_next = wsi->tls.pending_read_list_next;
+	lws_start_foreach_dll_safe(struct lws_dll_lws *, p, p1,
+				   pt->tls.pending_tls_head.next) {
+		struct lws *wsi = lws_container_of(p, struct lws,
+						   tls.pending_tls_list);
+
 		pt->fds[wsi->position_in_fds_table].revents |=
 			pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN;
 		ret |= pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN;
 
-		wsi = wsi_next;
-	}
+	} lws_end_foreach_dll_safe(p, p1);
 
 	return !!ret;
 }
@@ -49,29 +49,10 @@ lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt)
 void
 __lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
 {
-	struct lws_context *context = wsi->context;
-	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
-
-	if (!wsi->tls.pending_read_list_prev &&
-	    !wsi->tls.pending_read_list_next &&
-	    pt->tls.pending_read_list != wsi)
-		/* we are not on the list */
+	if (lws_dll_is_null(&wsi->tls.pending_tls_list))
 		return;
 
-	/* point previous guy's next to our next */
-	if (!wsi->tls.pending_read_list_prev)
-		pt->tls.pending_read_list = wsi->tls.pending_read_list_next;
-	else
-		wsi->tls.pending_read_list_prev->tls.pending_read_list_next =
-			wsi->tls.pending_read_list_next;
-
-	/* point next guy's previous to our previous */
-	if (wsi->tls.pending_read_list_next)
-		wsi->tls.pending_read_list_next->tls.pending_read_list_prev =
-			wsi->tls.pending_read_list_prev;
-
-	wsi->tls.pending_read_list_prev = NULL;
-	wsi->tls.pending_read_list_next = NULL;
+	lws_dll_lws_remove(&wsi->tls.pending_tls_list);
 }
 
 void