mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Backport of this changeset
http://lists.mysql.com/commits/59686 Cleanup pthread_self(), pthread_create(), pthread_join() implementation on Windows. Prior implementation is was unnecessarily complicated and even differs in embedded and non-embedded case. Improvements in this patch: * pthread_t is now the unique thread ID, instead of HANDLE returned by beginthread This simplifies pthread_self() to be just straight GetCurrentThreadId(). prior it was much art involved in passing the beginthread() handle from the caller to the TLS structure in the child thread ( did not work for the main thread of course) * remove MySQL specific my_thread_init()/my_thread_end() from pthread_create. No automagic is done on Unix on pthread_create(). Having the same on Windows will improve portability and avoid extra #ifdef's * remove redefinition of getpid() - it was defined as GetCurrentThreadId()
This commit is contained in:
parent
2801599323
commit
9cf8d12c85
9 changed files with 131 additions and 139 deletions
|
@ -27,6 +27,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/stat.h>
|
||||
#include <process.h> /* getpid()*/
|
||||
|
||||
|
||||
#define HAVE_SMEM 1
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
|
||||
#if defined(__WIN__)
|
||||
typedef CRITICAL_SECTION pthread_mutex_t;
|
||||
typedef HANDLE pthread_t;
|
||||
typedef DWORD pthread_t;
|
||||
typedef struct thread_attr {
|
||||
DWORD dwStackSize ;
|
||||
DWORD dwCreatingFlag ;
|
||||
|
@ -64,8 +64,7 @@ typedef struct {
|
|||
|
||||
|
||||
typedef int pthread_mutexattr_t;
|
||||
#define win_pthread_self my_thread_var->pthread_self
|
||||
#define pthread_self() win_pthread_self
|
||||
#define pthread_self() GetCurrentThreadId()
|
||||
#define pthread_handler_t EXTERNC void * __cdecl
|
||||
typedef void * (__cdecl *pthread_handler)(void *);
|
||||
|
||||
|
@ -99,7 +98,7 @@ struct timespec {
|
|||
(ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
|
||||
}
|
||||
|
||||
void win_pthread_init(void);
|
||||
|
||||
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||
int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
|
||||
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
|
||||
|
@ -116,11 +115,11 @@ int pthread_attr_destroy(pthread_attr_t *connect_att);
|
|||
struct tm *localtime_r(const time_t *timep,struct tm *tmp);
|
||||
struct tm *gmtime_r(const time_t *timep,struct tm *tmp);
|
||||
|
||||
void pthread_exit(void *a);
|
||||
int pthread_join(pthread_t thread, void **value_ptr);
|
||||
|
||||
void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
|
||||
|
||||
#define ETIMEDOUT 145 /* Win32 doesn't have this */
|
||||
#define getpid() GetCurrentThreadId()
|
||||
#define HAVE_LOCALTIME_R 1
|
||||
#define _REENTRANT 1
|
||||
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
|
||||
|
@ -145,7 +144,6 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
|
|||
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
|
||||
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
|
||||
|
||||
#define pthread_join(A,B) (WaitForSingleObject((A), INFINITE) != WAIT_OBJECT_0)
|
||||
|
||||
/* Dummy defines for easier code */
|
||||
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
|
||||
|
|
|
@ -130,7 +130,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
|
||||
../sql/partition_info.cc ../sql/sql_connect.cc
|
||||
../sql/scheduler.cc ../sql/event_parse_data.cc
|
||||
./sql/sql_signal.cc
|
||||
../sql/sql_signal.cc
|
||||
${GEN_SOURCES}
|
||||
${LIB_SOURCES})
|
||||
|
||||
|
|
|
@ -42,7 +42,9 @@ pthread_mutexattr_t my_fast_mutexattr;
|
|||
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
||||
pthread_mutexattr_t my_errorcheck_mutexattr;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
static void install_sigabrt_handler();
|
||||
#endif
|
||||
#ifdef TARGET_OS_LINUX
|
||||
|
||||
/*
|
||||
|
@ -145,15 +147,18 @@ my_bool my_thread_global_init(void)
|
|||
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
|
||||
pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&THR_COND_threads, NULL);
|
||||
#if defined( __WIN__) || defined(OS2)
|
||||
win_pthread_init();
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
|
||||
pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
|
||||
#endif
|
||||
#ifndef HAVE_GETHOSTBYNAME_R
|
||||
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
install_sigabrt_handler();
|
||||
#endif
|
||||
|
||||
if (my_thread_init())
|
||||
{
|
||||
my_thread_global_end(); /* Clean up */
|
||||
|
@ -268,11 +273,7 @@ my_bool my_thread_init(void)
|
|||
goto end;
|
||||
}
|
||||
pthread_setspecific(THR_KEY_mysys,tmp);
|
||||
#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
|
||||
tmp->pthread_self= (pthread_t) getpid();
|
||||
#else
|
||||
tmp->pthread_self= pthread_self();
|
||||
#endif
|
||||
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
|
||||
pthread_cond_init(&tmp->suspend, NULL);
|
||||
tmp->init= 1;
|
||||
|
@ -398,4 +399,30 @@ static uint get_thread_lib(void)
|
|||
return THD_LIB_OTHER;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
In Visual Studio 2005 and later, default SIGABRT handler will overwrite
|
||||
any unhandled exception filter set by the application and will try to
|
||||
call JIT debugger. This is not what we want, this we calling __debugbreak
|
||||
to stop in debugger, if process is being debugged or to generate
|
||||
EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
|
||||
*/
|
||||
|
||||
#if (_MSC_VER >= 1400)
|
||||
static void my_sigabrt_handler(int sig)
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
#endif /*_MSC_VER >=1400 */
|
||||
|
||||
static void install_sigabrt_handler(void)
|
||||
{
|
||||
#if (_MSC_VER >=1400)
|
||||
/*abort() should not override our exception filter*/
|
||||
_set_abort_behavior(0,_CALL_REPORTFAULT);
|
||||
signal(SIGABRT,my_sigabrt_handler);
|
||||
#endif /* _MSC_VER >=1400 */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* THREAD */
|
||||
|
|
|
@ -16,12 +16,11 @@
|
|||
/*****************************************************************************
|
||||
** The following is a simple implementation of posix conditions
|
||||
*****************************************************************************/
|
||||
#if defined(_WIN32)
|
||||
|
||||
#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
|
||||
#include "mysys_priv.h"
|
||||
#if defined(THREAD) && defined(__WIN__)
|
||||
#include <m_string.h>
|
||||
#undef getpid
|
||||
#include <process.h>
|
||||
#include <sys/timeb.h>
|
||||
|
||||
|
|
|
@ -14,33 +14,23 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/*****************************************************************************
|
||||
** Simulation of posix threads calls for WIN95 and NT
|
||||
** Simulation of posix threads calls for Windows
|
||||
*****************************************************************************/
|
||||
|
||||
#if defined (_WIN32)
|
||||
/* SAFE_MUTEX will not work until the thread structure is up to date */
|
||||
#undef SAFE_MUTEX
|
||||
|
||||
#include "mysys_priv.h"
|
||||
#if defined(THREAD) && defined(__WIN__)
|
||||
#include <m_string.h>
|
||||
#undef getpid
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
|
||||
static pthread_mutex_t THR_LOCK_thread;
|
||||
static void install_sigabrt_handler(void);
|
||||
|
||||
struct pthread_map
|
||||
struct thread_start_parameter
|
||||
{
|
||||
HANDLE pthreadself;
|
||||
pthread_handler func;
|
||||
void *param;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
void win_pthread_init(void)
|
||||
{
|
||||
pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Adapter to @c pthread_mutex_trylock()
|
||||
|
||||
|
@ -62,72 +52,81 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex)
|
|||
return EBUSY;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** We have tried to use '_beginthreadex' instead of '_beginthread' here
|
||||
** but in this case the program leaks about 512 characters for each
|
||||
** created thread !
|
||||
** As we want to save the created thread handler for other threads to
|
||||
** use and to be returned by pthread_self() (instead of the Win32 pseudo
|
||||
** handler), we have to go trough pthread_start() to catch the returned handler
|
||||
** in the new thread.
|
||||
*/
|
||||
|
||||
pthread_handler_t pthread_start(void *param)
|
||||
static unsigned int __stdcall pthread_start(void *p)
|
||||
{
|
||||
pthread_handler func=((struct pthread_map *) param)->func;
|
||||
void *func_param=((struct pthread_map *) param)->param;
|
||||
my_thread_init(); /* Will always succeed in windows */
|
||||
pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */
|
||||
win_pthread_self=((struct pthread_map *) param)->pthreadself;
|
||||
pthread_mutex_unlock(&THR_LOCK_thread);
|
||||
free((char*) param); /* Free param from create */
|
||||
pthread_exit((void*) (*func)(func_param));
|
||||
return 0; /* Safety */
|
||||
struct thread_start_parameter *par= (struct thread_start_parameter *)p;
|
||||
pthread_handler func= par->func;
|
||||
void *arg= par->arg;
|
||||
free(p);
|
||||
(*func)(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,
|
||||
pthread_handler func, void *param)
|
||||
pthread_handler func, void *param)
|
||||
{
|
||||
HANDLE hThread;
|
||||
struct pthread_map *map;
|
||||
uintptr_t handle;
|
||||
struct thread_start_parameter *par;
|
||||
unsigned int stack_size;
|
||||
DBUG_ENTER("pthread_create");
|
||||
|
||||
if (!(map=malloc(sizeof(*map))))
|
||||
DBUG_RETURN(-1);
|
||||
map->func=func;
|
||||
map->param=param;
|
||||
pthread_mutex_lock(&THR_LOCK_thread);
|
||||
#ifdef __BORLANDC__
|
||||
hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,
|
||||
attr->dwStackSize ? attr->dwStackSize :
|
||||
65535, (void*) map);
|
||||
#else
|
||||
hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
|
||||
attr->dwStackSize ? attr->dwStackSize :
|
||||
65535, (void*) map);
|
||||
#endif
|
||||
DBUG_PRINT("info", ("hThread=%lu",(long) hThread));
|
||||
*thread_id=map->pthreadself=hThread;
|
||||
pthread_mutex_unlock(&THR_LOCK_thread);
|
||||
par= (struct thread_start_parameter *)malloc(sizeof(*par));
|
||||
if (!par)
|
||||
goto error_return;
|
||||
|
||||
if (hThread == (HANDLE) -1)
|
||||
{
|
||||
int error=errno;
|
||||
DBUG_PRINT("error",
|
||||
("Can't create thread to handle request (error %d)",error));
|
||||
DBUG_RETURN(error ? error : -1);
|
||||
}
|
||||
VOID(SetThreadPriority(hThread, attr->priority)) ;
|
||||
par->func= func;
|
||||
par->arg= param;
|
||||
stack_size= attr?attr->dwStackSize:0;
|
||||
|
||||
handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
|
||||
if (!handle)
|
||||
goto error_return;
|
||||
DBUG_PRINT("info", ("thread id=%u",*thread_id));
|
||||
|
||||
/* Do not need thread handle, close it */
|
||||
CloseHandle((HANDLE)handle);
|
||||
DBUG_RETURN(0);
|
||||
|
||||
error_return:
|
||||
DBUG_PRINT("error",
|
||||
("Can't create thread to handle request (error %d)",errno));
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
|
||||
void pthread_exit(void *a)
|
||||
{
|
||||
_endthread();
|
||||
_endthreadex(0);
|
||||
}
|
||||
|
||||
int pthread_join(pthread_t thread, void **value_ptr)
|
||||
{
|
||||
DWORD ret;
|
||||
HANDLE handle;
|
||||
|
||||
handle= OpenThread(SYNCHRONIZE, FALSE, thread);
|
||||
if (!handle)
|
||||
{
|
||||
errno= EINVAL;
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
ret= WaitForSingleObject(handle, INFINITE);
|
||||
|
||||
if(ret != WAIT_OBJECT_0)
|
||||
{
|
||||
errno= EINVAL;
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return 0;
|
||||
|
||||
error_return:
|
||||
if(handle)
|
||||
CloseHandle(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -805,7 +805,10 @@ static void set_server_version(void);
|
|||
static int init_thread_environment();
|
||||
static char *get_relative_path(const char *path);
|
||||
static int fix_paths(void);
|
||||
pthread_handler_t handle_connections_sockets(void *arg);
|
||||
void handle_connections_sockets();
|
||||
#ifdef _WIN32
|
||||
pthread_handler_t handle_connections_sockets_thread(void *arg);
|
||||
#endif
|
||||
pthread_handler_t kill_server_thread(void *arg);
|
||||
static void bootstrap(FILE *file);
|
||||
static bool read_init_file(char *file_name);
|
||||
|
@ -2034,29 +2037,7 @@ static BOOL WINAPI console_event_handler( DWORD type )
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
In Visual Studio 2005 and later, default SIGABRT handler will overwrite
|
||||
any unhandled exception filter set by the application and will try to
|
||||
call JIT debugger. This is not what we want, this we calling __debugbreak
|
||||
to stop in debugger, if process is being debugged or to generate
|
||||
EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
|
||||
*/
|
||||
|
||||
#if (_MSC_VER >= 1400)
|
||||
static void my_sigabrt_handler(int sig)
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
#endif /*_MSC_VER >=1400 */
|
||||
|
||||
void win_install_sigabrt_handler(void)
|
||||
{
|
||||
#if (_MSC_VER >=1400)
|
||||
/*abort() should not override our exception filter*/
|
||||
_set_abort_behavior(0,_CALL_REPORTFAULT);
|
||||
signal(SIGABRT,my_sigabrt_handler);
|
||||
#endif /* _MSC_VER >=1400 */
|
||||
}
|
||||
|
||||
#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
|
||||
#define DEBUGGER_ATTACH_TIMEOUT 120
|
||||
|
@ -2135,7 +2116,6 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
|
|||
|
||||
static void init_signals(void)
|
||||
{
|
||||
win_install_sigabrt_handler();
|
||||
if(opt_console)
|
||||
SetConsoleCtrlHandler(console_event_handler,TRUE);
|
||||
|
||||
|
@ -4132,7 +4112,8 @@ static void create_shutdown_thread()
|
|||
#ifdef __WIN__
|
||||
hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
|
||||
pthread_t hThread;
|
||||
if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
|
||||
if (pthread_create(&hThread,&connection_attrib,
|
||||
handle_connections_sockets_thread, 0))
|
||||
sql_print_warning("Can't create thread to handle shutdown requests");
|
||||
|
||||
// On "Stop Service" we have to do regular shutdown
|
||||
|
@ -4177,7 +4158,7 @@ static void handle_connections_methods()
|
|||
{
|
||||
handler_count++;
|
||||
if (pthread_create(&hThread,&connection_attrib,
|
||||
handle_connections_sockets, 0))
|
||||
handle_connections_sockets_thread, 0))
|
||||
{
|
||||
sql_print_warning("Can't create thread to handle TCP/IP");
|
||||
handler_count--;
|
||||
|
@ -4506,18 +4487,11 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
|||
pthread_cond_signal(&COND_server_started);
|
||||
pthread_mutex_unlock(&LOCK_server_started);
|
||||
|
||||
#if defined(__NT__) || defined(HAVE_SMEM)
|
||||
#if defined(_WIN32) || defined(HAVE_SMEM)
|
||||
handle_connections_methods();
|
||||
#else
|
||||
#ifdef __WIN__
|
||||
if (!have_tcpip || opt_disable_networking)
|
||||
{
|
||||
sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
|
||||
unireg_abort(1);
|
||||
}
|
||||
#endif
|
||||
handle_connections_sockets(0);
|
||||
#endif /* __NT__ */
|
||||
handle_connections_sockets();
|
||||
#endif /* _WIN32 || HAVE_SMEM */
|
||||
|
||||
/* (void) pthread_attr_destroy(&connection_attrib); */
|
||||
|
||||
|
@ -4992,7 +4966,7 @@ inline void kill_broken_server()
|
|||
/* Handle new connections and spawn new process to handle them */
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
|
||||
void handle_connections_sockets()
|
||||
{
|
||||
my_socket sock,new_sock;
|
||||
uint error_count=0;
|
||||
|
@ -5195,13 +5169,19 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
|
|||
|
||||
create_new_thread(thd);
|
||||
}
|
||||
|
||||
decrement_handler_count();
|
||||
DBUG_RETURN(0);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __NT__
|
||||
#ifdef _WIN32
|
||||
pthread_handler_t handle_connections_sockets_thread(void *arg)
|
||||
{
|
||||
my_thread_init();
|
||||
handle_connections_sockets();
|
||||
decrement_handler_count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
pthread_handler_t handle_connections_namedpipes(void *arg)
|
||||
{
|
||||
HANDLE hConnectedPipe;
|
||||
|
|
|
@ -39,10 +39,6 @@
|
|||
#define MIN_HANDSHAKE_SIZE 6
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
#ifdef __WIN__
|
||||
extern void win_install_sigabrt_handler();
|
||||
#endif
|
||||
|
||||
/*
|
||||
Get structure for logging connection data for the current user
|
||||
*/
|
||||
|
@ -612,13 +608,8 @@ void thd_init_client_charset(THD *thd, uint cs_number)
|
|||
bool init_new_connection_handler_thread()
|
||||
{
|
||||
pthread_detach_this_thread();
|
||||
#if defined(__WIN__)
|
||||
win_install_sigabrt_handler();
|
||||
#else
|
||||
/* Win32 calls this in pthread_create */
|
||||
if (my_thread_init())
|
||||
return 1;
|
||||
#endif /* __WIN__ */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2498,7 +2498,6 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||
since it does not find one in the list.
|
||||
*/
|
||||
pthread_mutex_lock(&di->mutex);
|
||||
#if !defined( __WIN__) /* Win32 calls this in pthread_create */
|
||||
if (my_thread_init())
|
||||
{
|
||||
/* Can't use my_error since store_globals has not yet been called */
|
||||
|
@ -2506,13 +2505,9 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||
ER(ER_OUT_OF_RESOURCES), NULL);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
handle_delayed_insert_impl(thd, di);
|
||||
|
||||
#ifndef __WIN__
|
||||
end:
|
||||
#endif
|
||||
/*
|
||||
di should be unlinked from the thread handler list and have no active
|
||||
clients
|
||||
|
|
Loading…
Add table
Reference in a new issue