From 28528abbcd13174854551effe9e6f33f60dea93b Mon Sep 17 00:00:00 2001 From: Brad Keifer <15224368+bradkeifer@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:36:37 +1100 Subject: [PATCH 1/4] Initial changes to support systems with single arg pthread_setname_np() --- configure.ac | 16 ++++++++++++++-- src/misc.c | 26 +++++++++++++++++--------- src/misc.h | 4 ++-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 66d92954..fe14ab37 100644 --- a/configure.ac +++ b/configure.ac @@ -80,8 +80,19 @@ AC_SEARCH_LIBS([pthread_setname_np], [pthread], AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], [[pthread_setname_np(pthread_self(), "name");]])], [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_PTHREAD_SETNAME_NP], 1, - [Define to 1 if you have pthread_setname_np])], + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_2], 1, + [Define to 1 if you have pthread_setname_np with 2 args])], + [AC_MSG_RESULT([[no]])])], + [AC_SEARCH_LIBS([pthread_set_name_np], [pthread], + [AC_CHECK_FUNCS([pthread_set_name_np])])]) +AC_SEARCH_LIBS([pthread_setname_np], [pthread], + [dnl Validate pthread_setname_np with 1 arg (some have 2) + AC_MSG_CHECKING([[for single-parameter pthread_setname_np]]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], + [[pthread_setname_np("name");]])], + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_1], 1, + [Define to 1 if you have pthread_setname_np with 1 arg])], [AC_MSG_RESULT([[no]])])], [AC_SEARCH_LIBS([pthread_set_name_np], [pthread], [AC_CHECK_FUNCS([pthread_set_name_np])])]) @@ -94,6 +105,7 @@ AC_SEARCH_LIBS([pthread_getname_np], [pthread], AC_SEARCH_LIBS([pthread_getthreadid_np], [pthread], [AC_DEFINE([HAVE_PTHREAD_GETTHREADID_NP], 1, [Define to 1 if you have pthread_getthreadid_np])]) + AC_SEARCH_LIBS([uuid_generate_random], [uuid], [AC_DEFINE([HAVE_UUID], 1, [Define to 1 if you have uuid_generate_random])]) diff --git a/src/misc.c b/src/misc.c index 885e0a23..8f0b9263 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1852,14 +1852,16 @@ mutex_init(pthread_mutex_t *mutex) return err; } -int -thread_gettid() +int64_t +thread_gettid(pthread_t p) { - int tid = -1; + int64_t tid = -1; #if defined(HAVE_GETTID) - tid = (int)gettid(); + tid = (int64_t)gettid(); #elif defined(HAVE_PTHREAD_GETTHREADID_NP) - tid = pthread_getthreadid_np(); + tid = (int64_t)pthread_getthreadid_np(); +#else //defacto thread id + tid = (int64_t)p; #endif return tid; } @@ -1879,19 +1881,25 @@ thread_getname(pthread_t thread, char *name, size_t len) void thread_getnametid(char *buf, size_t len) { - int tid; + int64_t tid; char thread_name[32]; pthread_t p = pthread_self(); thread_getname(p, thread_name, sizeof(thread_name)); - tid = thread_gettid() % 10000; - snprintf(buf, len, "%s (%d)", thread_name, tid); + tid = thread_gettid(p) % 10000; + snprintf(buf, len, "%s (%" PRId64 ")", thread_name, tid); } void thread_setname(pthread_t thread, const char *name) { -#if defined(HAVE_PTHREAD_SETNAME_NP) +#if defined(HAVE_PTHREAD_SETNAME_NP_1) + pthread_setname_np(name); + DPRINTF(E_DBG, L_MISC, + "%s: Single argument pthread_setname_np(%s). Be aware! It must be called from thread whose name is to be changed\n", + __func__, name + ); +#elif defined(HAVE_PTHREAD_SETNAME_NP_2) pthread_setname_np(thread, name); #elif defined(HAVE_PTHREAD_SET_NAME_NP) pthread_set_name_np(thread, name); diff --git a/src/misc.h b/src/misc.h index 40612eb8..dce0eda7 100644 --- a/src/misc.h +++ b/src/misc.h @@ -319,8 +319,8 @@ int mutex_init(pthread_mutex_t *mutex); // wrapper for gettid/pthread_getthreadid_np -int -thread_gettid(); +int64_t +thread_gettid(pthread_t p); // wrapper for pthread_getname_np/pthread_get_name_np void From 9c8728f10f61edd943d68a5ee9d49206a88f2080 Mon Sep 17 00:00:00 2001 From: Brad Keifer <15224368+bradkeifer@users.noreply.github.com> Date: Sun, 9 Nov 2025 18:52:35 +1100 Subject: [PATCH 2/4] Move calls to thread_setname() into the thread start routines and move to a single argument thread_setname() --- src/cache.c | 2 +- src/evthr.c | 2 ++ src/httpd.c | 2 +- src/input.c | 4 ++-- src/inputs/pipe.c | 3 +-- src/inputs/spotify_librespotc.c | 2 +- src/library.c | 4 ++-- src/misc.c | 6 +++--- src/misc.h | 2 +- src/mpd.c | 4 ++-- src/outputs/airplay_events.c | 4 ++-- src/player.c | 4 ++-- src/websocket.c | 3 +-- src/worker.c | 2 +- 14 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/cache.c b/src/cache.c index 21642d8c..0c66c8c3 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1690,6 +1690,7 @@ cache(void *arg) int ret; int i; + thread_setname("cache"); ret = cache_open(); if (ret < 0) { @@ -2062,7 +2063,6 @@ cache_init(void) CHECK_NULL(L_CACHE, cmdbase = commands_base_new(evbase_cache, NULL)); CHECK_ERR(L_CACHE, pthread_create(&tid_cache, NULL, cache, NULL)); - thread_setname(tid_cache, "cache"); DPRINTF(E_INFO, L_CACHE, "Cache thread init\n"); diff --git a/src/evthr.c b/src/evthr.c index 0c236cdc..559f72f0 100644 --- a/src/evthr.c +++ b/src/evthr.c @@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "evthr.h" +#include "misc.h" #ifndef TAILQ_FOREACH_SAFE #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ @@ -135,6 +136,7 @@ _evthr_loop(void *args) pthread_exit(NULL); } + thread_setname("evthr"); thread->evbase = event_base_new(); thread->event = event_new(thread->evbase, thread->rdr, EV_READ | EV_PERSIST, _evthr_read_cmd, args); diff --git a/src/httpd.c b/src/httpd.c index ae421b97..963994a6 100644 --- a/src/httpd.c +++ b/src/httpd.c @@ -1538,7 +1538,7 @@ thread_init_cb(struct evthr *thr, void *shared) struct event_base *evbase; httpd_server *server; - thread_setname(pthread_self(), "httpd"); + thread_setname("httpd"); CHECK_ERR(L_HTTPD, db_perthread_init()); CHECK_NULL(L_HTTPD, evbase = evthr_get_base(thr)); diff --git a/src/input.c b/src/input.c index 5d7dbba4..14cd4ea2 100644 --- a/src/input.c +++ b/src/input.c @@ -656,6 +656,8 @@ input(void *arg) { int ret; + thread_setname("input"); + ret = db_perthread_init(); if (ret < 0) { @@ -932,8 +934,6 @@ input_init(void) goto thread_fail; } - thread_setname(tid_input, "input"); - return 0; thread_fail: diff --git a/src/inputs/pipe.c b/src/inputs/pipe.c index 21d3800a..5648923b 100644 --- a/src/inputs/pipe.c +++ b/src/inputs/pipe.c @@ -817,6 +817,7 @@ pipe_watch_update(void *arg, int *retval) static void * pipe_thread_run(void *arg) { + thread_setname("pipe"); event_base_dispatch(evbase_pipe); pthread_exit(NULL); @@ -934,8 +935,6 @@ pipe_thread_start(void) CHECK_NULL(L_PLAYER, evbase_pipe = event_base_new()); CHECK_NULL(L_PLAYER, cmdbase = commands_base_new(evbase_pipe, NULL)); CHECK_ERR(L_PLAYER, pthread_create(&tid_pipe, NULL, pipe_thread_run, NULL)); - - thread_setname(tid_pipe, "pipe"); } static void diff --git a/src/inputs/spotify_librespotc.c b/src/inputs/spotify_librespotc.c index c7c5a2fa..c6cb46b6 100644 --- a/src/inputs/spotify_librespotc.c +++ b/src/inputs/spotify_librespotc.c @@ -240,7 +240,7 @@ tcp_disconnect(int fd) static void thread_name_set(pthread_t thread) { - thread_setname(thread, "spotify"); + thread_setname("spotify"); } static void diff --git a/src/library.c b/src/library.c index a21f22e5..2467cdde 100644 --- a/src/library.c +++ b/src/library.c @@ -1005,6 +1005,8 @@ library(void *arg) { int ret; + thread_setname("library"); + #ifdef __linux__ struct sched_param param; @@ -1074,8 +1076,6 @@ library_init(void) CHECK_ERR(L_LIB, pthread_create(&tid_library, NULL, library, NULL)); - thread_setname(tid_library, "library"); - return 0; } diff --git a/src/misc.c b/src/misc.c index 8f0b9263..4cfe45e9 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1891,7 +1891,7 @@ thread_getnametid(char *buf, size_t len) } void -thread_setname(pthread_t thread, const char *name) +thread_setname(const char *name) { #if defined(HAVE_PTHREAD_SETNAME_NP_1) pthread_setname_np(name); @@ -1900,9 +1900,9 @@ thread_setname(pthread_t thread, const char *name) __func__, name ); #elif defined(HAVE_PTHREAD_SETNAME_NP_2) - pthread_setname_np(thread, name); + pthread_setname_np(pthread_self(), name); #elif defined(HAVE_PTHREAD_SET_NAME_NP) - pthread_set_name_np(thread, name); + pthread_set_name_np(pthread_self(), name); #endif } diff --git a/src/misc.h b/src/misc.h index dce0eda7..ca4bbfb9 100644 --- a/src/misc.h +++ b/src/misc.h @@ -331,7 +331,7 @@ thread_getnametid(char *buf, size_t len); // wrapper for pthread_setname_np/pthread_set_name_np void -thread_setname(pthread_t thread, const char *name); +thread_setname(const char *name); void uuid_make(char *str); diff --git a/src/mpd.c b/src/mpd.c index bd0f6a92..b2a8b3d0 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -4242,6 +4242,8 @@ mpd(void *arg) { int ret; + thread_setname("mpd"); + ret = db_perthread_init(); if (ret < 0) { @@ -4370,8 +4372,6 @@ mpd_init(void) goto thread_fail; } - thread_setname(tid_mpd, "mpd"); - mpd_clients = NULL; listener_add(mpd_listener_cb, MPD_ALL_IDLE_LISTENER_EVENTS, NULL); diff --git a/src/outputs/airplay_events.c b/src/outputs/airplay_events.c index 7a6f77f6..d3e657e2 100644 --- a/src/outputs/airplay_events.c +++ b/src/outputs/airplay_events.c @@ -470,6 +470,8 @@ incoming_cb(int fd, short what, void *arg) static void * airplay_events(void *arg) { + + thread_setname("airplay events"); event_base_dispatch(evbase); pthread_exit(NULL); @@ -519,8 +521,6 @@ airplay_events_init(void) goto error; } -// TODO thread_name_set(thread_id, "airplay events"); - return 0; error: diff --git a/src/player.c b/src/player.c index 8b77c254..d1053e42 100644 --- a/src/player.c +++ b/src/player.c @@ -3839,6 +3839,8 @@ player(void *arg) struct output_device *device; int ret; + thread_setname("player"); + ret = db_perthread_init(); if (ret < 0) { @@ -3954,8 +3956,6 @@ player_init(void) goto error_input_deinit; } - thread_setname(tid_player, "player"); - return 0; error_input_deinit: diff --git a/src/websocket.c b/src/websocket.c index ca259b48..c1b15a9f 100644 --- a/src/websocket.c +++ b/src/websocket.c @@ -415,6 +415,7 @@ static struct lws_protocols protocols[] = static void * websocket(void *arg) { + thread_setname("websocket"); listener_add(listener_cb, LISTENER_UPDATE | LISTENER_DATABASE | LISTENER_PAIRING | LISTENER_SPOTIFY | LISTENER_LASTFM | LISTENER_SPEAKER | LISTENER_PLAYER | LISTENER_OPTIONS | LISTENER_VOLUME | LISTENER_QUEUE, NULL); @@ -533,8 +534,6 @@ websocket_init(void) return -1; } - thread_setname(tid_websocket, "websocket"); - websocket_is_initialized = true; return 0; diff --git a/src/worker.c b/src/worker.c index ecbc9836..01161443 100644 --- a/src/worker.c +++ b/src/worker.c @@ -100,7 +100,7 @@ init_cb(struct evthr *thr, void *shared) worker_thr = thr; - thread_setname(pthread_self(), "worker"); + thread_setname("worker"); } static void From 38e1c89908744c9fad2374b0799997a5621d9291 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Sat, 8 Nov 2025 10:01:48 +0100 Subject: [PATCH 3/4] [misc] Fix crash after pipe metadata parsing error from xml_free(NULL) xml_free() should be a no-op when called with null Closes #1940 --- src/misc_xml.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/misc_xml.c b/src/misc_xml.c index a98cc7c7..ac558982 100644 --- a/src/misc_xml.c +++ b/src/misc_xml.c @@ -111,6 +111,9 @@ xml_from_file(const char *path) void xml_free(xml_node *top) { + if (!top || !top->doc) + return; + xmlFreeDoc(top->doc); } From ec66f95269093a6ea1245c4af6a2f4be6a3a2fbc Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Tue, 11 Nov 2025 23:19:05 +0100 Subject: [PATCH 4/4] [misc] PR #1941 adjustments --- configure.ac | 30 ++++++++++++--------------- src/cache.c | 1 + src/evthr.c | 1 + src/inputs/pipe.c | 1 + src/misc.c | 40 ++++++++++++++++-------------------- src/misc.h | 7 +++---- src/outputs/airplay_events.c | 1 + src/websocket.c | 1 + 8 files changed, 39 insertions(+), 43 deletions(-) diff --git a/configure.ac b/configure.ac index fe14ab37..7d572cda 100644 --- a/configure.ac +++ b/configure.ac @@ -75,33 +75,29 @@ AC_SEARCH_LIBS([timer_settime], [rt], AC_SEARCH_LIBS([pthread_exit], [pthread], [], [AC_MSG_ERROR([[pthreads library is required]])]) AC_SEARCH_LIBS([pthread_setname_np], [pthread], - [dnl Validate pthread_setname_np with 2 args (some have 1) - AC_MSG_CHECKING([[for two-parameter pthread_setname_np]]) + [AC_MSG_CHECKING([[for two-parameter pthread_setname_np]]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], [[pthread_setname_np(pthread_self(), "name");]])], [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_2], 1, + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP], 1, [Define to 1 if you have pthread_setname_np with 2 args])], - [AC_MSG_RESULT([[no]])])], - [AC_SEARCH_LIBS([pthread_set_name_np], [pthread], - [AC_CHECK_FUNCS([pthread_set_name_np])])]) -AC_SEARCH_LIBS([pthread_setname_np], [pthread], - [dnl Validate pthread_setname_np with 1 arg (some have 2) - AC_MSG_CHECKING([[for single-parameter pthread_setname_np]]) + [AC_MSG_RESULT([[no]])]) + AC_MSG_CHECKING([[for MacOS single-parameter pthread_setname_np]]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], [[pthread_setname_np("name");]])], [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_1], 1, + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP_MACOS], 1, [Define to 1 if you have pthread_setname_np with 1 arg])], - [AC_MSG_RESULT([[no]])])], - [AC_SEARCH_LIBS([pthread_set_name_np], [pthread], - [AC_CHECK_FUNCS([pthread_set_name_np])])]) + [AC_MSG_RESULT([[no]])])]) +AC_SEARCH_LIBS([pthread_set_name_np], [pthread], + [AC_DEFINE([HAVE_PTHREAD_SET_NAME_NP], 1, + [Define to 1 if you have pthread_set_name_np])]) AC_SEARCH_LIBS([pthread_getname_np], [pthread], [AC_DEFINE([HAVE_PTHREAD_GETNAME_NP], 1, - [Define to 1 if you have pthread_getname_np])] - [AC_SEARCH_LIBS([pthread_get_name_np], [pthread], - [AC_DEFINE([HAVE_PTHREAD_GETNAME_NP], 1, - [Define to 1 if you have pthread_get_name_np])])]) + [Define to 1 if you have pthread_getname_np])]) +AC_SEARCH_LIBS([pthread_get_name_np], [pthread], + [AC_DEFINE([HAVE_PTHREAD_GET_NAME_NP], 1, + [Define to 1 if you have pthread_get_name_np])]) AC_SEARCH_LIBS([pthread_getthreadid_np], [pthread], [AC_DEFINE([HAVE_PTHREAD_GETTHREADID_NP], 1, [Define to 1 if you have pthread_getthreadid_np])]) diff --git a/src/cache.c b/src/cache.c index 0c66c8c3..1071a948 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1691,6 +1691,7 @@ cache(void *arg) int i; thread_setname("cache"); + ret = cache_open(); if (ret < 0) { diff --git a/src/evthr.c b/src/evthr.c index 559f72f0..9e2d0c1e 100644 --- a/src/evthr.c +++ b/src/evthr.c @@ -137,6 +137,7 @@ _evthr_loop(void *args) } thread_setname("evthr"); + thread->evbase = event_base_new(); thread->event = event_new(thread->evbase, thread->rdr, EV_READ | EV_PERSIST, _evthr_read_cmd, args); diff --git a/src/inputs/pipe.c b/src/inputs/pipe.c index 5648923b..83a0300a 100644 --- a/src/inputs/pipe.c +++ b/src/inputs/pipe.c @@ -818,6 +818,7 @@ static void * pipe_thread_run(void *arg) { thread_setname("pipe"); + event_base_dispatch(evbase_pipe); pthread_exit(NULL); diff --git a/src/misc.c b/src/misc.c index 4cfe45e9..dfe06731 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1852,55 +1852,51 @@ mutex_init(pthread_mutex_t *mutex) return err; } -int64_t -thread_gettid(pthread_t p) +int +thread_gettid(void) { - int64_t tid = -1; + int tid; #if defined(HAVE_GETTID) - tid = (int64_t)gettid(); + tid = (int)gettid(); #elif defined(HAVE_PTHREAD_GETTHREADID_NP) - tid = (int64_t)pthread_getthreadid_np(); + tid = pthread_getthreadid_np(); #else //defacto thread id - tid = (int64_t)p; + tid = (int)pthread_self(); #endif return tid; } void -thread_getname(pthread_t thread, char *name, size_t len) +thread_getname(char *name, size_t len) { #if defined(HAVE_PTHREAD_GETNAME_NP) - pthread_getname_np(thread, name, len); + pthread_getname_np(pthread_self(), name, len); #elif defined(HAVE_PTHREAD_GET_NAME_NP) - pthread_get_name_np(thread, name, len); + pthread_get_name_np(pthread_self(), name, len); #else - name[0] = '\0'; + if (len > 0) + name[0] = '\0'; #endif } void thread_getnametid(char *buf, size_t len) { - int64_t tid; + int tid; char thread_name[32]; - pthread_t p = pthread_self(); - thread_getname(p, thread_name, sizeof(thread_name)); - tid = thread_gettid(p) % 10000; - snprintf(buf, len, "%s (%" PRId64 ")", thread_name, tid); + thread_getname(thread_name, sizeof(thread_name)); + tid = thread_gettid() % 10000; + snprintf(buf, len, "%s (%d)", thread_name, tid); } void thread_setname(const char *name) { -#if defined(HAVE_PTHREAD_SETNAME_NP_1) - pthread_setname_np(name); - DPRINTF(E_DBG, L_MISC, - "%s: Single argument pthread_setname_np(%s). Be aware! It must be called from thread whose name is to be changed\n", - __func__, name - ); -#elif defined(HAVE_PTHREAD_SETNAME_NP_2) +#if defined(HAVE_PTHREAD_SETNAME_NP) pthread_setname_np(pthread_self(), name); +#elif defined(HAVE_PTHREAD_SETNAME_NP_MACOS) + pthread_setname_np(name); #elif defined(HAVE_PTHREAD_SET_NAME_NP) pthread_set_name_np(pthread_self(), name); #endif diff --git a/src/misc.h b/src/misc.h index ca4bbfb9..0a6c2493 100644 --- a/src/misc.h +++ b/src/misc.h @@ -318,13 +318,12 @@ buildopts_get(void); int mutex_init(pthread_mutex_t *mutex); -// wrapper for gettid/pthread_getthreadid_np -int64_t -thread_gettid(pthread_t p); +int +thread_gettid(void); // wrapper for pthread_getname_np/pthread_get_name_np void -thread_getname(pthread_t thread, char *name, size_t len); +thread_getname(char *name, size_t len); void thread_getnametid(char *buf, size_t len); diff --git a/src/outputs/airplay_events.c b/src/outputs/airplay_events.c index d3e657e2..8e38cbd8 100644 --- a/src/outputs/airplay_events.c +++ b/src/outputs/airplay_events.c @@ -472,6 +472,7 @@ airplay_events(void *arg) { thread_setname("airplay events"); + event_base_dispatch(evbase); pthread_exit(NULL); diff --git a/src/websocket.c b/src/websocket.c index c1b15a9f..f775befa 100644 --- a/src/websocket.c +++ b/src/websocket.c @@ -416,6 +416,7 @@ static void * websocket(void *arg) { thread_setname("websocket"); + listener_add(listener_cb, LISTENER_UPDATE | LISTENER_DATABASE | LISTENER_PAIRING | LISTENER_SPOTIFY | LISTENER_LASTFM | LISTENER_SPEAKER | LISTENER_PLAYER | LISTENER_OPTIONS | LISTENER_VOLUME | LISTENER_QUEUE, NULL);