Problem: ZMQ background threads are unnamed

Solution: use pthread API to set the name. For now call every thread
"ZMQ b/g thread". Would be nice to number the I/O threads and name
explicitly the reaper thread, but in reality a bit of internal API
churn would be necessary, so perhaps it's not worth it.
This is useful when debugging a process with many threads.
This commit is contained in:
Luca Boccassi 2017-02-28 19:45:23 +00:00
parent 3548d5e950
commit 3ab4796c5a
7 changed files with 137 additions and 0 deletions

View File

@ -323,6 +323,7 @@ zmq_check_tcp_keepidle ()
zmq_check_tcp_keepintvl ()
zmq_check_tcp_keepalive ()
zmq_check_tcp_tipc ()
zmq_check_pthread_setname ()
if ( CMAKE_SYSTEM_NAME MATCHES "Linux"

View File

@ -176,3 +176,55 @@ int main(int argc, char *argv [])
"
ZMQ_HAVE_TIPC)
endmacro()
macro(zmq_check_pthread_setname)
message(STATUS "Checking pthread_setname signature")
set(SAVE_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-D_GNU_SOURCE -Werror -pthread")
check_c_source_runs(
"
#include <pthread.h>
int main(int argc, char *argv [])
{
pthread_setname_np (\"foo\");
return 0;
}
"
ZMQ_HAVE_PTHREAD_SETNAME_1)
check_c_source_runs(
"
#include <pthread.h>
int main(int argc, char *argv [])
{
pthread_setname_np (pthread_self(), \"foo\");
return 0;
}
"
ZMQ_HAVE_PTHREAD_SETNAME_2)
check_c_source_runs(
"
#include <pthread.h>
int main(int argc, char *argv [])
{
pthread_setname_np (pthread_self(), \"foo\", (void *)0);
return 0;
}
"
ZMQ_HAVE_PTHREAD_SETNAME_3)
check_c_source_runs(
"
#include <pthread.h>
int main(int argc, char *argv [])
{
pthread_set_name_np (pthread_self(), \"foo\");
return 0;
}
"
ZMQ_HAVE_PTHREAD_SET_NAME)
set(CMAKE_REQUIRED_FLAGS ${SAVE_CMAKE_REQUIRED_FLAGS})
endmacro()

View File

@ -29,6 +29,10 @@
#cmakedefine ZMQ_HAVE_TCP_KEEPIDLE
#cmakedefine ZMQ_HAVE_TCP_KEEPINTVL
#cmakedefine ZMQ_HAVE_TCP_KEEPALIVE
#cmakedefine ZMQ_HAVE_PTHREAD_SETNAME_1
#cmakedefine ZMQ_HAVE_PTHREAD_SETNAME_2
#cmakedefine ZMQ_HAVE_PTHREAD_SETNAME_3
#cmakedefine ZMQ_HAVE_PTHREAD_SET_NAME
#cmakedefine ZMQ_HAVE_OPENPGM
#cmakedefine ZMQ_MAKE_VALGRIND_HAPPY

View File

@ -589,6 +589,56 @@ AC_TYPE_SIGNAL
AC_CHECK_FUNCS(perror gettimeofday clock_gettime memset socket getifaddrs freeifaddrs fork posix_memalign mkdtemp)
AC_CHECK_HEADERS([alloca.h])
# pthread_setname is non-posix, and there are at least 4 different implementations
AC_MSG_CHECKING([whether signature of pthread_setname_np() has 1 argument])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <pthread.h>]],
[[pthread_setname_np ("foo"); return 0;]])
],[
AC_MSG_RESULT([yes])
AC_DEFINE(ZMQ_HAVE_PTHREAD_SETNAME_1, [1],
[Whether pthread_setname_np() has 1 argument])
],[
AC_MSG_RESULT([no])
])
AC_MSG_CHECKING([whether signature of pthread_setname_np() has 2 arguments])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <pthread.h>]],
[[pthread_setname_np (pthread_self (), "foo"); return 0;]])
],[
AC_MSG_RESULT([yes])
AC_DEFINE(ZMQ_HAVE_PTHREAD_SETNAME_2, [1],
[Whether pthread_setname_np() has 2 arguments])
],[
AC_MSG_RESULT([no])
])
AC_MSG_CHECKING([whether signature of pthread_setname_np() has 3 arguments])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <pthread.h>]],
[[pthread_setname_np (pthread_self(), "foo", (void *)0); return 0;]])
],[
AC_MSG_RESULT([yes])
AC_DEFINE(ZMQ_HAVE_PTHREAD_SETNAME_3, [1],
[Whether pthread_setname_np() has 3 arguments])
],[
AC_MSG_RESULT([no])
])
AC_MSG_CHECKING([whether pthread_set_name_np() exists])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <pthread.h>]],
[[pthread_set_name_np (pthread_self(), "foo"); return 0;]])
],[
AC_MSG_RESULT([yes])
AC_DEFINE(ZMQ_HAVE_PTHREAD_SET_NAME, [1],
[Whether pthread_set_name_np() exists])
],[
AC_MSG_RESULT([no])
])
LIBZMQ_CHECK_SOCK_CLOEXEC([
AC_DEFINE([ZMQ_HAVE_SOCK_CLOEXEC],
[1],

View File

@ -412,6 +412,7 @@ void zmq::ctx_t::start_thread (thread_t &thread_, thread_fn *tfn_, void *arg_) c
{
thread_.start(tfn_, arg_);
thread_.setSchedulingParameters(thread_priority, thread_sched_policy);
thread_.setThreadName ("ZMQ b/g thread");
}
void zmq::ctx_t::send_command (uint32_t tid_, const command_t &command_)

View File

@ -77,6 +77,12 @@ void zmq::thread_t::setSchedulingParameters(int priority_, int schedulingPolicy_
LIBZMQ_UNUSED (schedulingPolicy_);
}
void zmq::thread_t::setThreadName(const char *name_)
{
// not implemented
LIBZMQ_UNUSED (name_);
}
#else
#include <signal.h>
@ -159,4 +165,23 @@ void zmq::thread_t::setSchedulingParameters(int priority_, int schedulingPolicy_
#endif
}
void zmq::thread_t::setThreadName(const char *name_)
{
if (!name_)
return;
#if defined(HAVE_PTHREAD_SETNAME_1)
int rc = pthread_setname_np(name_);
posix_assert (rc);
#elif defined(HAVE_PTHREAD_SETNAME_2)
int rc = pthread_setname_np(descriptor, name_);
posix_assert (rc);
#elif defined(HAVE_PTHREAD_SETNAME_3)
int rc = pthread_setname_np(descriptor, name_, NULL);
posix_assert (rc);
#elif defined(HAVE_PTHREAD_SET_NAME)
pthread_set_name_np(descriptor, name_);
#endif
}
#endif

View File

@ -67,6 +67,10 @@ namespace zmq
// pthread. Has no effect on other platforms.
void setSchedulingParameters(int priority_, int schedulingPolicy_);
// Sets the thread name, 16 characters max including terminating NUL.
// Only implemented for pthread. Has no effect on other platforms.
void setThreadName(const char *name_);
// These are internal members. They should be private, however then
// they would not be accessible from the main C routine of the thread.
thread_fn *tfn;