Unverified Commit 2b63a896 authored by Luca Boccassi's avatar Luca Boccassi Committed by GitHub

Merge pull request #3515 from moretromain/win-threadname

Implement thread_t::setThreadName() on windows
parents 046ccfc4 27005cc1
...@@ -426,14 +426,10 @@ void zmq::thread_ctx_t::start_thread (thread_t &thread_, ...@@ -426,14 +426,10 @@ void zmq::thread_ctx_t::start_thread (thread_t &thread_,
_thread_affinity_cpus); _thread_affinity_cpus);
char namebuf[16] = ""; char namebuf[16] = "";
#ifdef ZMQ_HAVE_WINDOWS
LIBZMQ_UNUSED (name_);
#else
snprintf (namebuf, sizeof (namebuf), "%s%sZMQbg%s%s", snprintf (namebuf, sizeof (namebuf), "%s%sZMQbg%s%s",
_thread_name_prefix.empty () ? "" : _thread_name_prefix.c_str (), _thread_name_prefix.empty () ? "" : _thread_name_prefix.c_str (),
_thread_name_prefix.empty () ? "" : "/", name_ ? "/" : "", _thread_name_prefix.empty () ? "" : "/", name_ ? "/" : "",
name_ ? name_ : ""); name_ ? name_ : "");
#endif
thread_.start (tfn_, arg_, namebuf); thread_.start (tfn_, arg_, namebuf);
} }
......
...@@ -57,10 +57,8 @@ zmq::io_thread_t::~io_thread_t () ...@@ -57,10 +57,8 @@ zmq::io_thread_t::~io_thread_t ()
void zmq::io_thread_t::start () void zmq::io_thread_t::start ()
{ {
char name[16] = ""; char name[16] = "";
#ifndef ZMQ_HAVE_WINDOWS
snprintf (name, sizeof (name), "IO/%u", snprintf (name, sizeof (name), "IO/%u",
get_tid () - zmq::ctx_t::reaper_tid - 1); get_tid () - zmq::ctx_t::reaper_tid - 1);
#endif
// Start the underlying I/O thread. // Start the underlying I/O thread.
_poller->start (name); _poller->start (name);
} }
......
...@@ -47,6 +47,7 @@ static unsigned int __stdcall thread_routine (void *arg_) ...@@ -47,6 +47,7 @@ static unsigned int __stdcall thread_routine (void *arg_)
#endif #endif
{ {
zmq::thread_t *self = (zmq::thread_t *) arg_; zmq::thread_t *self = (zmq::thread_t *) arg_;
self->applyThreadName ();
self->_tfn (self->_arg); self->_tfn (self->_arg);
return 0; return 0;
} }
...@@ -54,9 +55,10 @@ static unsigned int __stdcall thread_routine (void *arg_) ...@@ -54,9 +55,10 @@ static unsigned int __stdcall thread_routine (void *arg_)
void zmq::thread_t::start (thread_fn *tfn_, void *arg_, const char *name_) void zmq::thread_t::start (thread_fn *tfn_, void *arg_, const char *name_)
{ {
LIBZMQ_UNUSED (name_);
_tfn = tfn_; _tfn = tfn_;
_arg = arg_; _arg = arg_;
if (name_)
strncpy (_name, name_, sizeof (_name));
#if defined _WIN32_WCE #if defined _WIN32_WCE
_descriptor = _descriptor =
(HANDLE) CreateThread (NULL, 0, &::thread_routine, this, 0, NULL); (HANDLE) CreateThread (NULL, 0, &::thread_routine, this, 0, NULL);
...@@ -92,10 +94,48 @@ void zmq::thread_t::setSchedulingParameters ( ...@@ -92,10 +94,48 @@ void zmq::thread_t::setSchedulingParameters (
LIBZMQ_UNUSED (affinity_cpus_); LIBZMQ_UNUSED (affinity_cpus_);
} }
void zmq::thread_t::setThreadName (const char *name_) void zmq::thread_t::
applySchedulingParameters () // to be called in secondary thread context
{ {
// not implemented // not implemented
LIBZMQ_UNUSED (name_); }
namespace
{
#pragma pack(push, 8)
struct thread_info_t
{
DWORD _type;
LPCSTR _name;
DWORD _thread_id;
DWORD _flags;
};
#pragma pack(pop)
}
void zmq::thread_t::
applyThreadName () // to be called in secondary thread context
{
if (!_name[0])
return;
thread_info_t thread_info;
thread_info._type = 0x1000;
thread_info._name = _name;
thread_info._thread_id = -1;
thread_info._flags = 0;
#pragma warning(push)
#pragma warning(disable : 6320 6322)
__try {
DWORD MS_VC_EXCEPTION = 0x406D1388;
RaiseException (MS_VC_EXCEPTION, 0,
sizeof (thread_info) / sizeof (ULONG_PTR),
(ULONG_PTR *) &thread_info);
}
__except (EXCEPTION_CONTINUE_EXECUTION) {
}
#pragma warning(pop)
} }
#elif defined ZMQ_HAVE_VXWORKS #elif defined ZMQ_HAVE_VXWORKS
...@@ -154,10 +194,10 @@ void zmq::thread_t:: ...@@ -154,10 +194,10 @@ void zmq::thread_t::
} }
} }
void zmq::thread_t::setThreadName (const char *name_) void zmq::thread_t::
applyThreadName () // to be called in secondary thread context
{ {
// not implemented // not implemented
LIBZMQ_UNUSED (name_);
} }
#else #else
...@@ -181,7 +221,7 @@ static void *thread_routine (void *arg_) ...@@ -181,7 +221,7 @@ static void *thread_routine (void *arg_)
#endif #endif
zmq::thread_t *self = (zmq::thread_t *) arg_; zmq::thread_t *self = (zmq::thread_t *) arg_;
self->applySchedulingParameters (); self->applySchedulingParameters ();
self->setThreadName (self->_name.c_str ()); self->applyThreadName ();
self->_tfn (self->_arg); self->_tfn (self->_arg);
return NULL; return NULL;
} }
...@@ -191,7 +231,8 @@ void zmq::thread_t::start (thread_fn *tfn_, void *arg_, const char *name_) ...@@ -191,7 +231,8 @@ void zmq::thread_t::start (thread_fn *tfn_, void *arg_, const char *name_)
{ {
_tfn = tfn_; _tfn = tfn_;
_arg = arg_; _arg = arg_;
_name = name_; if (name_)
strncpy (_name, name_, sizeof (_name));
int rc = pthread_create (&_descriptor, NULL, thread_routine, this); int rc = pthread_create (&_descriptor, NULL, thread_routine, this);
posix_assert (rc); posix_assert (rc);
_started = true; _started = true;
...@@ -301,7 +342,8 @@ void zmq::thread_t:: ...@@ -301,7 +342,8 @@ void zmq::thread_t::
#endif #endif
} }
void zmq::thread_t::setThreadName (const char *name_) void zmq::thread_t::
applyThreadName () // to be called in secondary thread context
{ {
/* The thread name is a cosmetic string, added to ease debugging of /* The thread name is a cosmetic string, added to ease debugging of
* multi-threaded applications. It is not a big issue if this value * multi-threaded applications. It is not a big issue if this value
...@@ -310,7 +352,7 @@ void zmq::thread_t::setThreadName (const char *name_) ...@@ -310,7 +352,7 @@ void zmq::thread_t::setThreadName (const char *name_)
* "int rc" is retained where available, to help debuggers stepping * "int rc" is retained where available, to help debuggers stepping
* through code to see its value - but otherwise it is ignored. * through code to see its value - but otherwise it is ignored.
*/ */
if (!name_) if (!_name[0])
return; return;
/* Fails with permission denied on Android 5/6 */ /* Fails with permission denied on Android 5/6 */
...@@ -319,19 +361,19 @@ void zmq::thread_t::setThreadName (const char *name_) ...@@ -319,19 +361,19 @@ void zmq::thread_t::setThreadName (const char *name_)
#endif #endif
#if defined(ZMQ_HAVE_PTHREAD_SETNAME_1) #if defined(ZMQ_HAVE_PTHREAD_SETNAME_1)
int rc = pthread_setname_np (name_); int rc = pthread_setname_np (_name);
if (rc) if (rc)
return; return;
#elif defined(ZMQ_HAVE_PTHREAD_SETNAME_2) #elif defined(ZMQ_HAVE_PTHREAD_SETNAME_2)
int rc = pthread_setname_np (pthread_self (), name_); int rc = pthread_setname_np (pthread_self (), _name);
if (rc) if (rc)
return; return;
#elif defined(ZMQ_HAVE_PTHREAD_SETNAME_3) #elif defined(ZMQ_HAVE_PTHREAD_SETNAME_3)
int rc = pthread_setname_np (pthread_self (), name_, NULL); int rc = pthread_setname_np (pthread_self (), _name, NULL);
if (rc) if (rc)
return; return;
#elif defined(ZMQ_HAVE_PTHREAD_SET_NAME) #elif defined(ZMQ_HAVE_PTHREAD_SET_NAME)
pthread_set_name_np (pthread_self (), name_); pthread_set_name_np (pthread_self (), _name);
#endif #endif
} }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <pthread.h> #include <pthread.h>
#endif #endif
#include <set> #include <set>
#include <string> #include <cstring>
namespace zmq namespace zmq
{ {
...@@ -56,11 +56,11 @@ class thread_t ...@@ -56,11 +56,11 @@ class thread_t
inline thread_t () : inline thread_t () :
_tfn (NULL), _tfn (NULL),
_arg (NULL), _arg (NULL),
_name (""),
_started (false), _started (false),
_thread_priority (ZMQ_THREAD_PRIORITY_DFLT), _thread_priority (ZMQ_THREAD_PRIORITY_DFLT),
_thread_sched_policy (ZMQ_THREAD_SCHED_POLICY_DFLT) _thread_sched_policy (ZMQ_THREAD_SCHED_POLICY_DFLT)
{ {
memset (_name, 0, sizeof (_name));
} }
#ifdef ZMQ_HAVE_VXWORKS #ifdef ZMQ_HAVE_VXWORKS
...@@ -74,6 +74,8 @@ class thread_t ...@@ -74,6 +74,8 @@ class thread_t
// Creates OS thread. 'tfn' is main thread function. It'll be passed // Creates OS thread. 'tfn' is main thread function. It'll be passed
// 'arg' as an argument. // 'arg' as an argument.
// Name is 16 characters max including terminating NUL. Thread naming is
// implemented only for pthread, and windows when a debugger is attached.
void start (thread_fn *tfn_, void *arg_, const char *name_); void start (thread_fn *tfn_, void *arg_, const char *name_);
// Returns whether the thread was started, i.e. start was called. // Returns whether the thread was started, i.e. start was called.
...@@ -92,16 +94,13 @@ class thread_t ...@@ -92,16 +94,13 @@ class thread_t
int scheduling_policy_, int scheduling_policy_,
const std::set<int> &affinity_cpus_); const std::set<int> &affinity_cpus_);
// 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 // These are internal members. They should be private, however then
// they would not be accessible from the main C routine of the thread. // they would not be accessible from the main C routine of the thread.
void applySchedulingParameters (); void applySchedulingParameters ();
void applyThreadName ();
thread_fn *_tfn; thread_fn *_tfn;
void *_arg; void *_arg;
std::string _name; char _name[16];
private: private:
bool _started; bool _started;
......
...@@ -95,3 +95,10 @@ static inline int poll (struct pollfd *pfd, unsigned long nfds, int timeout) ...@@ -95,3 +95,10 @@ static inline int poll (struct pollfd *pfd, unsigned long nfds, int timeout)
#define AI_NUMERICSERV 0x0400 #define AI_NUMERICSERV 0x0400
#endif #endif
#endif #endif
// In MSVC prior to v14, snprintf is not available
// The closest implementation is the _snprintf_s function
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf(buffer_, count_, format_, ...) \
_snprintf_s (buffer_, count_, _TRUNCATE, format_, __VA_ARGS__)
#endif
...@@ -48,10 +48,6 @@ ...@@ -48,10 +48,6 @@
char error_message_buffer[256]; char error_message_buffer[256];
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif
void *handler; void *handler;
void *zap_thread; void *zap_thread;
void *server; void *server;
......
...@@ -96,6 +96,13 @@ enum ...@@ -96,6 +96,13 @@ enum
}; };
#endif #endif
// In MSVC prior to v14, snprintf is not available
// The closest implementation is the _snprintf_s function
#if defined _MSC_VER && _MSC_VER < 1900
#define snprintf(buffer_, count_, format_, ...) \
_snprintf_s (buffer_, count_, _TRUNCATE, format_, __VA_ARGS__)
#endif
#define LIBZMQ_UNUSED(object) (void) object #define LIBZMQ_UNUSED(object) (void) object
// Bounce a message from client to server and back // Bounce a message from client to server and back
......
...@@ -35,10 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -35,10 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <unity.h> #include <unity.h>
#if defined(_MSC_VER) && _MSC_VER <= 1800
#define snprintf _snprintf
#endif
// Internal helper functions that are not intended to be directly called from // Internal helper functions that are not intended to be directly called from
// tests. They must be declared in the header since they are used by macros. // tests. They must be declared in the header since they are used by macros.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment