mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-32537 Name threads to improve debugging experience and diagnostics.
Use SetThreadDescription/pthread_setname_np to give threads a name.
This commit is contained in:
parent
584fc85e21
commit
5bd0516488
14 changed files with 131 additions and 36 deletions
|
@ -1624,6 +1624,12 @@ typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread);
|
|||
*/
|
||||
typedef struct PSI_thread* (*get_thread_v1_t)(void);
|
||||
|
||||
/**
|
||||
Get name of the thread, according to the thread class.
|
||||
The name is returns without the thread/subsystem prefix.
|
||||
*/
|
||||
typedef const char* (*get_thread_class_name_v1_t)(void);
|
||||
|
||||
/**
|
||||
Assign a user name to the instrumented thread.
|
||||
@param user the user name
|
||||
|
@ -2538,6 +2544,8 @@ struct PSI_v1
|
|||
set_thread_os_id_v1_t set_thread_os_id;
|
||||
/** @sa get_thread_v1_t. */
|
||||
get_thread_v1_t get_thread;
|
||||
/** @sa get_thread_name_v1_t. */
|
||||
get_thread_class_name_v1_t get_thread_class_name;
|
||||
/** @sa set_thread_user_v1_t. */
|
||||
set_thread_user_v1_t set_thread_user;
|
||||
/** @sa set_thread_account_v1_t. */
|
||||
|
|
|
@ -449,6 +449,7 @@ typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread,
|
|||
ulonglong id);
|
||||
typedef void (*set_thread_os_id_v1_t)(struct PSI_thread *thread);
|
||||
typedef struct PSI_thread* (*get_thread_v1_t)(void);
|
||||
typedef const char* (*get_thread_class_name_v1_t)(void);
|
||||
typedef void (*set_thread_user_v1_t)(const char *user, int user_len);
|
||||
typedef void (*set_thread_account_v1_t)(const char *user, int user_len,
|
||||
const char *host, int host_len);
|
||||
|
@ -725,6 +726,7 @@ struct PSI_v1
|
|||
set_thread_THD_v1_t set_thread_THD;
|
||||
set_thread_os_id_v1_t set_thread_os_id;
|
||||
get_thread_v1_t get_thread;
|
||||
get_thread_class_name_v1_t get_thread_class_name;
|
||||
set_thread_user_v1_t set_thread_user;
|
||||
set_thread_account_v1_t set_thread_account;
|
||||
set_thread_db_v1_t set_thread_db;
|
||||
|
|
|
@ -80,6 +80,8 @@ void pfs_set_thread_os_id_v1(PSI_thread *thread);
|
|||
PSI_thread*
|
||||
pfs_get_thread_v1(void);
|
||||
|
||||
const char *pfs_get_thread_class_name_v1(void);
|
||||
|
||||
void pfs_set_thread_user_v1(const char *user, int user_len);
|
||||
|
||||
void pfs_set_thread_account_v1(const char *user, int user_len,
|
||||
|
|
|
@ -46,7 +46,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c my_default.c
|
|||
my_rdtsc.c psi_noop.c
|
||||
my_atomic_writes.c my_cpu.c my_likely.c my_largepage.c
|
||||
file_logger.c my_dlerror.c crc32/crc32c.cc
|
||||
my_timezone.cc)
|
||||
my_timezone.cc my_thread_name.cc)
|
||||
|
||||
IF (WIN32)
|
||||
SET (MYSYS_SOURCES ${MYSYS_SOURCES}
|
||||
|
|
|
@ -172,35 +172,6 @@ my_bool my_thread_global_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MAX_THREAD_NAME 256
|
||||
#elif defined(__linux__)
|
||||
#define MAX_THREAD_NAME 16
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
void my_thread_set_name(const char *name)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wchar_t wname[MAX_THREAD_NAME];
|
||||
wname[0]= 0;
|
||||
MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, MAX_THREAD_NAME);
|
||||
SetThreadDescription(GetCurrentThread(), wname);
|
||||
#elif defined __linux__
|
||||
char shortname[MAX_THREAD_NAME];
|
||||
snprintf(shortname, MAX_THREAD_NAME, "%s", name);
|
||||
pthread_setname_np(pthread_self(), shortname);
|
||||
#elif defined __NetBSD__
|
||||
pthread_setname_np(pthread_self(), "%s", (void *) name);
|
||||
#elif defined __FreeBSD__ || defined __OpenBSD__
|
||||
pthread_set_name_np(pthread_self(), name);
|
||||
#elif defined __APPLE__
|
||||
pthread_setname_np(name);
|
||||
#else
|
||||
(void) name;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
End the mysys thread system. Called when ending the last thread
|
||||
|
|
97
mysys/my_thread_name.cc
Normal file
97
mysys/my_thread_name.cc
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* Copyright 2024, MariaDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_pthread.h>
|
||||
#include <my_sys.h>
|
||||
#include "mysql/psi/psi.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MAX_THREAD_NAME 256
|
||||
typedef HRESULT (*func_SetThreadDescription)(HANDLE,PCWSTR);
|
||||
#elif defined(__linux__)
|
||||
#define MAX_THREAD_NAME 16
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PSI_THREAD_INTERFACE) && !defined DBUG_OFF
|
||||
/**
|
||||
Check that the name is consistent with PSI.
|
||||
Require that the name matches the last part of PSI's class name
|
||||
(e.g. "thread/sql/main" -> "main").
|
||||
|
||||
We drop the namespace prefix, because these thread names are
|
||||
truncated to 15 characters on Linux, and something like "innodb/" would
|
||||
already take up about half of that.
|
||||
*/
|
||||
static void dbug_verify_thread_name(const char *name)
|
||||
{
|
||||
const char *psi_name= NULL;
|
||||
const char *thread_class_name= PSI_THREAD_CALL(get_thread_class_name)();
|
||||
if (thread_class_name)
|
||||
{
|
||||
/* Remove the path prefix */
|
||||
const char *last_part= strrchr(thread_class_name, '/');
|
||||
if (last_part)
|
||||
psi_name= last_part + 1;
|
||||
else
|
||||
psi_name= thread_class_name;
|
||||
}
|
||||
if (psi_name && strcmp(psi_name, name))
|
||||
{
|
||||
fprintf(stderr, "my_thread_set_name() mismatch: PSI name '%s' != '%s'\n",
|
||||
psi_name, name);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define dbug_verify_thread_name(name) do {} while (0)
|
||||
#endif
|
||||
|
||||
/* Set current thread name for debugger/profiler and similar tools. */
|
||||
extern "C" void my_thread_set_name(const char *name)
|
||||
{
|
||||
dbug_verify_thread_name(name);
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
SetThreadDescription might not be there on older Windows versions.
|
||||
Load it dynamically.
|
||||
*/
|
||||
static func_SetThreadDescription my_SetThreadDescription=
|
||||
(func_SetThreadDescription) GetProcAddress(GetModuleHandle("kernel32"),
|
||||
"SetThreadDescription");
|
||||
if (!my_SetThreadDescription)
|
||||
return;
|
||||
wchar_t wname[MAX_THREAD_NAME];
|
||||
wname[0]= 0;
|
||||
MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, MAX_THREAD_NAME);
|
||||
my_SetThreadDescription(GetCurrentThread(), wname);
|
||||
#elif defined __linux__
|
||||
char shortname[MAX_THREAD_NAME];
|
||||
snprintf(shortname, MAX_THREAD_NAME, "%s", name);
|
||||
pthread_setname_np(pthread_self(), shortname);
|
||||
#elif defined __NetBSD__
|
||||
pthread_setname_np(pthread_self(), "%s", (void *) name);
|
||||
#elif defined __FreeBSD__ || defined __OpenBSD__
|
||||
pthread_set_name_np(pthread_self(), name);
|
||||
#elif defined __APPLE__
|
||||
pthread_setname_np(name);
|
||||
#else
|
||||
(void) name;
|
||||
#endif
|
||||
}
|
|
@ -228,6 +228,11 @@ get_thread_noop(void NNN)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char* get_thread_class_name_noop(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void set_thread_user_noop(const char *user NNN, int user_len NNN)
|
||||
{
|
||||
return;
|
||||
|
@ -938,6 +943,7 @@ static PSI PSI_noop=
|
|||
set_thread_THD_noop,
|
||||
set_thread_os_id_noop,
|
||||
get_thread_noop,
|
||||
get_thread_class_name_noop,
|
||||
set_thread_user_noop,
|
||||
set_thread_user_host_noop,
|
||||
set_thread_db_noop,
|
||||
|
|
|
@ -3219,7 +3219,7 @@ pthread_handler_t signal_hand(void *)
|
|||
sigset_t set;
|
||||
int sig;
|
||||
my_thread_init(); // Init new thread
|
||||
my_thread_set_name("signal_hand");
|
||||
my_thread_set_name("signal_handler");
|
||||
signal_thread_in_use= 1;
|
||||
|
||||
if (test_flags & TEST_SIGINT)
|
||||
|
|
|
@ -1226,7 +1226,7 @@ handle_rpl_parallel_thread(void *arg)
|
|||
struct rpl_parallel_thread *rpt= (struct rpl_parallel_thread *)arg;
|
||||
|
||||
my_thread_init();
|
||||
my_thread_set_name("rpl_parallel");
|
||||
my_thread_set_name("rpl_parallel_thread");
|
||||
thd = new THD(next_thread_id());
|
||||
thd->thread_stack = (char*)&thd;
|
||||
server_threads.insert(thd);
|
||||
|
|
|
@ -33,7 +33,7 @@ pthread_handler_t ack_receive_handler(void *arg)
|
|||
Ack_receiver *recv= reinterpret_cast<Ack_receiver *>(arg);
|
||||
|
||||
my_thread_init();
|
||||
my_thread_set_name("ack_receive");
|
||||
my_thread_set_name("Ack_receiver");
|
||||
recv->run();
|
||||
my_thread_end();
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused)))
|
|||
struct timespec abstime;
|
||||
bool reset_flush_time = TRUE;
|
||||
my_thread_init();
|
||||
my_thread_set_name("handle_manager");
|
||||
my_thread_set_name("manager");
|
||||
DBUG_ENTER("handle_manager");
|
||||
|
||||
pthread_detach_this_thread();
|
||||
|
|
|
@ -1534,7 +1534,7 @@ static void *worker_main(void *param)
|
|||
worker_thread_t this_thread;
|
||||
pthread_detach_this_thread();
|
||||
my_thread_init();
|
||||
my_thread_set_name("connection_worker");
|
||||
my_thread_set_name("worker_thread");
|
||||
|
||||
DBUG_ENTER("worker_main");
|
||||
|
||||
|
|
|
@ -577,7 +577,7 @@ pthread_handler_t ma_checkpoint_background(void *arg)
|
|||
PAGECACHE_FILE *UNINIT_VAR(kfile); /**< index file currently being flushed */
|
||||
|
||||
my_thread_init();
|
||||
my_thread_set_name("ma_checkpoint_background");
|
||||
my_thread_set_name("checkpoint_background");
|
||||
DBUG_PRINT("info",("Maria background checkpoint thread starts"));
|
||||
DBUG_ASSERT(interval > 0);
|
||||
|
||||
|
|
|
@ -2325,6 +2325,14 @@ pfs_get_thread_v1(void)
|
|||
return reinterpret_cast<PSI_thread*> (pfs);
|
||||
}
|
||||
|
||||
const char *pfs_get_thread_class_name_v1(void)
|
||||
{
|
||||
PFS_thread *pfs= my_thread_get_THR_PFS();
|
||||
if (!pfs)
|
||||
return NULL;
|
||||
return pfs->m_class->m_name;
|
||||
}
|
||||
|
||||
/**
|
||||
Implementation of the thread instrumentation interface.
|
||||
@sa PSI_v1::set_thread_user.
|
||||
|
@ -7040,6 +7048,7 @@ PSI_v1 PFS_v1=
|
|||
pfs_set_thread_THD_v1,
|
||||
pfs_set_thread_os_id_v1,
|
||||
pfs_get_thread_v1,
|
||||
pfs_get_thread_class_name_v1,
|
||||
pfs_set_thread_user_v1,
|
||||
pfs_set_thread_account_v1,
|
||||
pfs_set_thread_db_v1,
|
||||
|
|
Loading…
Reference in a new issue