aboutsummaryrefslogtreecommitdiff
path: root/lib/conncache.h
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2019-12-09 11:53:54 +0100
committerDaniel Stenberg <daniel@haxx.se>2019-12-09 15:30:09 +0100
commitee263de7a378e701f15e58879f36fdcfe8742006 (patch)
tree5fdf1aafe027c7e659cfaa989f429b5159645a79 /lib/conncache.h
parent9e891ff54de34d0e4c9aec502eb53e5b64a6dd1f (diff)
conncache: fix multi-thread use of shared connection cache
It could accidentally let the connection get used by more than one thread, leading to double-free and more. Reported-by: Christopher Reid Fixes #4544 Closes #4557
Diffstat (limited to 'lib/conncache.h')
-rw-r--r--lib/conncache.h24
1 files changed, 23 insertions, 1 deletions
diff --git a/lib/conncache.h b/lib/conncache.h
index 58f902409..5fe80b4c8 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -42,6 +42,27 @@ struct conncache {
#define BUNDLE_UNKNOWN 0 /* initial value */
#define BUNDLE_MULTIPLEX 2
+#ifdef CURLDEBUG
+/* the debug versions of these macros make extra certain that the lock is
+ never doubly locked or unlocked */
+#define CONN_LOCK(x) if((x)->share) { \
+ Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
+ DEBUGASSERT(!(x)->state.conncache_lock); \
+ (x)->state.conncache_lock = TRUE; \
+ }
+
+#define CONN_UNLOCK(x) if((x)->share) { \
+ DEBUGASSERT((x)->state.conncache_lock); \
+ (x)->state.conncache_lock = FALSE; \
+ Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
+ }
+#else
+#define CONN_LOCK(x) if((x)->share) \
+ Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
+#define CONN_UNLOCK(x) if((x)->share) \
+ Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
+#endif
+
struct connectbundle {
int multiuse; /* supports multi-use */
size_t num_connections; /* Number of connections in the bundle */
@@ -61,7 +82,8 @@ void Curl_conncache_unlock(struct Curl_easy *data);
size_t Curl_conncache_size(struct Curl_easy *data);
size_t Curl_conncache_bundle_size(struct connectdata *conn);
-bool Curl_conncache_return_conn(struct connectdata *conn);
+bool Curl_conncache_return_conn(struct Curl_easy *data,
+ struct connectdata *conn);
CURLcode Curl_conncache_add_conn(struct conncache *connc,
struct connectdata *conn) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct Curl_easy *data,