Commit a9f159ad05 for ffmpeg
commit a9f159ad0513e1651af7c71fb9eb4d5385e5855f
Author: Niklas Haas <git@haasn.dev>
Date: Tue Sep 29 20:46:32 2026 +0200
avformat/libcurl: properly lock CURLSH
This was previously rejected from my PR because "the CURLSH is only active
once the CURL * is added to the CURLM *" (paraphrased), however this is
not true - as we also curl_easy_setopt(CURLOPT_COOKIELIST) during
setup_curl(), called from the main thread, which references (and writes to)
the CURLSH, relying only on the lockfunc to synchronize access.
Fixes: 6c338a659551c8f395954698f8e0c8607c3e3f4c
Fixes: https://github.com/nxtedition/FFmpeg/issues/77
Signed-off-by: Niklas Haas <git@haasn.dev>
Sponsored-by: nxtedition AB
diff --git a/libavformat/libcurl.c b/libavformat/libcurl.c
index 3e53eadb3c..983b207722 100644
--- a/libavformat/libcurl.c
+++ b/libavformat/libcurl.c
@@ -91,7 +91,7 @@ typedef struct CurlLoop {
CURLM *multi;
CURLSH *share; /* shared cookies/HSTS */
- pthread_mutex_t mutex; /* guards the command queue, exit and cmd->done */
+ pthread_mutex_t mutex; /* guards the command queue, exit, share and cmd->done */
pthread_cond_t cond; /* signaled when a sync command completes */
CurlCmd *cmd_head, *cmd_tail;
int exit;
@@ -920,6 +920,20 @@ static int curl_dispatch(CurlLoop *loop, enum cmd_kind kind, CurlContext *c,
return 0;
}
+static void share_lock_callback(CURL *handle, curl_lock_data data,
+ curl_lock_access access, void *userdata)
+{
+ CurlLoop *loop = userdata;
+ pthread_mutex_lock(&loop->mutex);
+}
+
+static void share_unlock_callback(CURL *handle, curl_lock_data data,
+ void *userdata)
+{
+ CurlLoop *loop = userdata;
+ pthread_mutex_unlock(&loop->mutex);
+}
+
static CurlLoop *curl_loop_create(AVFormatContext *avfc)
{
CurlLoop *loop = av_mallocz(sizeof(*loop));
@@ -945,6 +959,9 @@ static CurlLoop *curl_loop_create(AVFormatContext *avfc)
loop->share = curl_share_init();
if (!loop->share)
goto fail3;
+ curl_share_setopt(loop->share, CURLSHOPT_USERDATA, loop);
+ curl_share_setopt(loop->share, CURLSHOPT_LOCKFUNC, share_lock_callback);
+ curl_share_setopt(loop->share, CURLSHOPT_UNLOCKFUNC, share_unlock_callback);
curl_share_setopt(loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
curl_share_setopt(loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);