memdebug: make logging thread-safe

This should make it work fine even when using threads, like in the
threaded resolver.
This commit is contained in:
Daniel Stenberg 2025-11-27 12:25:34 +01:00
parent aa9342058f
commit c7ca9ba1ac
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
5 changed files with 25 additions and 27 deletions

View file

@ -90,9 +90,9 @@ static long easy_init_flags;
#ifdef GLOBAL_INIT_IS_THREADSAFE
static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
#define global_init_lock() curl_simple_lock_lock(&s_lock)
#define global_init_unlock() curl_simple_lock_unlock(&s_lock)
static Curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
#define global_init_lock() Curl_simple_lock_lock(&s_lock)
#define global_init_unlock() Curl_simple_lock_unlock(&s_lock)
#else

View file

@ -30,11 +30,11 @@
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
#define curl_simple_lock SRWLOCK
#define Curl_simple_lock SRWLOCK
#define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT
#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
#define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
#define Curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
#define Curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
#elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H)
#include <stdatomic.h>
@ -42,7 +42,7 @@
#include <sched.h>
#endif
#define curl_simple_lock atomic_int
#define Curl_simple_lock atomic_int
#define CURL_SIMPLE_LOCK_INIT 0
#ifndef __INTEL_COMPILER
@ -61,7 +61,7 @@
#endif
static CURL_INLINE void curl_simple_lock_lock(curl_simple_lock *lock)
static CURL_INLINE void Curl_simple_lock_lock(Curl_simple_lock *lock)
{
for(;;) {
if(!atomic_exchange_explicit(lock, true, memory_order_acquire))
@ -82,7 +82,7 @@ static CURL_INLINE void curl_simple_lock_lock(curl_simple_lock *lock)
}
}
static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock)
static CURL_INLINE void Curl_simple_lock_unlock(Curl_simple_lock *lock)
{
atomic_store_explicit(lock, false, memory_order_release);
}
@ -91,10 +91,10 @@ static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock)
#include <pthread.h>
#define curl_simple_lock pthread_mutex_t
#define Curl_simple_lock pthread_mutex_t
#define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
#define curl_simple_lock_lock(m) pthread_mutex_lock(m)
#define curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
#define Curl_simple_lock_lock(m) pthread_mutex_lock(m)
#define Curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
#else

View file

@ -304,7 +304,7 @@ void Curl_dnscache_clear(struct Curl_easy *data)
return address that we can jump back to from inside a signal handler. This
is not thread-safe stuff. */
static sigjmp_buf curl_jmpenv;
static curl_simple_lock curl_jmpenv_lock;
static Curl_simple_lock curl_jmpenv_lock;
#endif
/* lookup address, returns entry if found and not stale */
@ -1072,7 +1072,7 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data,
This should be the last thing we do before calling Curl_resolv(),
as otherwise we would have to worry about variables that get modified
before we invoke Curl_resolv() (and thus use "volatile"). */
curl_simple_lock_lock(&curl_jmpenv_lock);
Curl_simple_lock_lock(&curl_jmpenv_lock);
if(sigsetjmp(curl_jmpenv, 1)) {
/* this is coming from a siglongjmp() after an alarm signal */
@ -1142,7 +1142,7 @@ clean_up:
#endif
#endif /* HAVE_SIGACTION */
curl_simple_lock_unlock(&curl_jmpenv_lock);
Curl_simple_lock_unlock(&curl_jmpenv_lock);
/* switch back the alarm() to either zero or to what it was before minus
the time we spent until now! */

View file

@ -30,6 +30,7 @@
#include "urldata.h"
#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW(), CURLX_FREOPEN_LOW() */
#include "easy_lock.h"
#ifdef USE_BACKTRACE
#include "backtrace.h"
@ -66,6 +67,11 @@ static long memsize = 0; /* set number of mallocs allowed */
static struct backtrace_state *btstate;
#endif
/* lock access to the debug log */
static Curl_simple_lock debug_lock = CURL_SIMPLE_LOCK_INIT;
#define memdebug_lock() Curl_simple_lock_lock(&debug_lock)
#define memdebug_unlock() Curl_simple_lock_unlock(&debug_lock)
/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected
on exit so the logfile must be closed explicitly or data could be lost.
Though _exit() does not call atexit handlers such as this, LSAN's call to
@ -525,8 +531,11 @@ void curl_dbg_log(const char *format, ...)
if(nchars > (int)sizeof(buf) - 1)
nchars = (int)sizeof(buf) - 1;
if(nchars > 0)
if(nchars > 0) {
memdebug_lock();
(fwrite)(buf, 1, (size_t)nchars, curl_dbg_logfile);
memdebug_unlock();
}
}
#endif /* CURLDEBUG */

View file

@ -851,10 +851,6 @@ sub checksystemfeatures {
die "cannot run torture tests since curl was built without ".
"TrackMemory feature (--enable-curldebug)";
}
if($feature{"threaded-resolver"} && !$valgrind) {
die "cannot run torture tests since curl was built with the ".
"threaded resolver, and we are not running with valgrind";
}
}
my $hostname=join(' ', runclientoutput("hostname"));
@ -879,13 +875,6 @@ sub checksystemfeatures {
# Only show if not the default for now
logmsg "* Jobs: $jobs\n";
}
# Disable memory tracking when using threaded resolver
if($feature{"TrackMemory"} && $feature{"threaded-resolver"}) {
logmsg("*\n",
"*** DISABLES TrackMemory (memory tracking) when using threaded resolver\n",
"*\n");
$feature{"TrackMemory"} = 0;
}
my $env = sprintf("%s%s%s%s%s",
$valgrind?"Valgrind ":"",