Commit c8a6c2c6 authored by jimw@mysql.com's avatar jimw@mysql.com

Fix wait_timeout (and kill) handling on Mac OS X by cleaning up how

signal handlers are set up, the blocking flags for sockets are set,
and which thread-related functions are used. (Bug #8731)
parent 52181cc8
...@@ -1102,7 +1102,7 @@ case $SYSTEM_TYPE in ...@@ -1102,7 +1102,7 @@ case $SYSTEM_TYPE in
*darwin5*) *darwin5*)
if test "$ac_cv_prog_gcc" = "yes" if test "$ac_cv_prog_gcc" = "yes"
then then
FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH" FLAGS="-traditional-cpp -DHAVE_DARWIN5_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
CFLAGS="$CFLAGS $FLAGS" CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS" CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O" MAX_C_OPTIMIZE="-O"
...@@ -1112,23 +1112,13 @@ case $SYSTEM_TYPE in ...@@ -1112,23 +1112,13 @@ case $SYSTEM_TYPE in
*darwin6*) *darwin6*)
if test "$ac_cv_prog_gcc" = "yes" if test "$ac_cv_prog_gcc" = "yes"
then then
FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH" FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
CFLAGS="$CFLAGS $FLAGS" CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS" CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O" MAX_C_OPTIMIZE="-O"
fi fi
;; ;;
*darwin[[7-8]]*) *darwin*)
# don't forget to escape [] like above
if test "$ac_cv_prog_gcc" = "yes"
then
FLAGS="-DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT"
CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
fi
;;
*darwin9*)
if test "$ac_cv_prog_gcc" = "yes" if test "$ac_cv_prog_gcc" = "yes"
then then
FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT" FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT"
......
...@@ -192,7 +192,7 @@ typedef uint rf_SetTimer; ...@@ -192,7 +192,7 @@ typedef uint rf_SetTimer;
/* Convert some simple functions to Posix */ /* Convert some simple functions to Posix */
#define sigset(A,B) signal((A),(B)) #define my_sigset(A,B) signal((A),(B))
#define finite(A) _finite(A) #define finite(A) _finite(A)
#define sleep(A) Sleep((A)*1000) #define sleep(A) Sleep((A)*1000)
#define popen(A) popen(A,B) _popen((A),(B)) #define popen(A) popen(A,B) _popen((A),(B))
......
...@@ -289,8 +289,6 @@ extern int my_pthread_create_detached; ...@@ -289,8 +289,6 @@ extern int my_pthread_create_detached;
#undef HAVE_PTHREAD_RWLOCK_RDLOCK #undef HAVE_PTHREAD_RWLOCK_RDLOCK
#undef HAVE_SNPRINTF #undef HAVE_SNPRINTF
#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B))
#define signal(A,B) pthread_signal((A),(void (*)(int)) (B))
#define my_pthread_attr_setprio(A,B) #define my_pthread_attr_setprio(A,B)
#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ #endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */
...@@ -322,14 +320,26 @@ extern int my_pthread_cond_init(pthread_cond_t *mp, ...@@ -322,14 +320,26 @@ extern int my_pthread_cond_init(pthread_cond_t *mp,
#if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX) #if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX)
int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */
#endif #endif
#if !defined(HAVE_SIGSET) && !defined(HAVE_mit_thread) && !defined(sigset)
#define sigset(A,B) do { struct sigaction s; sigset_t set; \
sigemptyset(&set); \ /*
s.sa_handler = (B); \ We define my_sigset() and use that instead of the system sigset() so that
s.sa_mask = set; \ we can favor an implementation based on sigaction(). On some systems, such
s.sa_flags = 0; \ as Mac OS X, sigset() results in flags such as SA_RESTART being set, and
sigaction((A), &s, (struct sigaction *) NULL); \ we want to make sure that no such flags are set.
} while (0) */
#if defined(HAVE_SIGACTION) && !defined(my_sigset)
#define my_sigset(A,B) do { struct sigaction s; sigset_t set; \
sigemptyset(&set); \
s.sa_handler = (B); \
s.sa_mask = set; \
s.sa_flags = 0; \
sigaction((A), &s, (struct sigaction *) NULL); \
} while (0)
#elif defined(HAVE_SIGSET) && !defined(my_sigset)
#define my_sigset(A,B) sigset((A),(B))
#elif !defined(my_sigset)
#define my_sigset(A,B) signal((A),(B))
#endif #endif
#ifndef my_pthread_setprio #ifndef my_pthread_setprio
...@@ -409,16 +419,13 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res); ...@@ -409,16 +419,13 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res);
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
#endif #endif
#ifdef HAVE_DARWIN_THREADS #ifdef HAVE_DARWIN5_THREADS
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) #define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
#define pthread_kill(A,B) pthread_dummy(0) #define pthread_kill(A,B) pthread_dummy(0)
#define pthread_condattr_init(A) pthread_dummy(0) #define pthread_condattr_init(A) pthread_dummy(0)
#define pthread_condattr_destroy(A) pthread_dummy(0) #define pthread_condattr_destroy(A) pthread_dummy(0)
#define pthread_signal(A,B) pthread_dummy(0)
#undef pthread_detach_this_thread #undef pthread_detach_this_thread
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); } #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); }
#undef sigset
#define sigset(A,B) pthread_signal((A),(void (*)(int)) (B))
#endif #endif
#if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER) #if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER)
......
select 1;
1
1
select 2;
ERROR HY000: MySQL server has gone away
select 3;
3
3
#
# Bug #8731: wait_timeout does not work on Mac OS X
#
--disable_reconnect
select 1;
# wait_timeout is 2, so we should get disconnected now
--sleep 5
--error 2006
select 2;
--enable_reconnect
select 3;
...@@ -404,23 +404,6 @@ int sigwait(sigset_t *setp, int *sigp) ...@@ -404,23 +404,6 @@ int sigwait(sigset_t *setp, int *sigp)
#endif /* DONT_USE_SIGSUSPEND */ #endif /* DONT_USE_SIGSUSPEND */
#endif /* HAVE_SIGWAIT */ #endif /* HAVE_SIGWAIT */
/*****************************************************************************
** Implement pthread_signal for systems that can't use signal() with threads
** Currently this is only used with BSDI 3.0
*****************************************************************************/
#ifdef USE_PTHREAD_SIGNAL
int pthread_signal(int sig, void (*func)())
{
struct sigaction sact;
sact.sa_flags= 0;
sact.sa_handler= func;
sigemptyset(&sact.sa_mask);
sigaction(sig, &sact, (struct sigaction*) 0);
return 0;
}
#endif
/**************************************************************************** /****************************************************************************
The following functions fixes that all pthread functions should work The following functions fixes that all pthread functions should work
......
...@@ -80,17 +80,7 @@ void init_thr_alarm(uint max_alarms) ...@@ -80,17 +80,7 @@ void init_thr_alarm(uint max_alarms)
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL); pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) #if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread) my_sigset(THR_CLIENT_ALARM,thread_alarm);
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */
#else
{
struct sigaction sact;
sact.sa_flags = 0;
bzero((char*) &sact, sizeof(sact));
sact.sa_handler = thread_alarm;
sigaction(THR_CLIENT_ALARM, &sact, (struct sigaction*) 0);
}
#endif
#endif #endif
sigemptyset(&s); sigemptyset(&s);
sigaddset(&s, THR_SERVER_ALARM); sigaddset(&s, THR_SERVER_ALARM);
...@@ -110,12 +100,12 @@ void init_thr_alarm(uint max_alarms) ...@@ -110,12 +100,12 @@ void init_thr_alarm(uint max_alarms)
#elif defined(USE_ONE_SIGNAL_HAND) #elif defined(USE_ONE_SIGNAL_HAND)
pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */
#if THR_SERVER_ALARM == THR_CLIENT_ALARM #if THR_SERVER_ALARM == THR_CLIENT_ALARM
sigset(THR_CLIENT_ALARM,process_alarm); /* Linuxthreads */ my_sigset(THR_CLIENT_ALARM,process_alarm); /* Linuxthreads */
pthread_sigmask(SIG_UNBLOCK, &s, NULL); pthread_sigmask(SIG_UNBLOCK, &s, NULL);
#endif #endif
#else #else
my_sigset(THR_SERVER_ALARM, process_alarm);
pthread_sigmask(SIG_UNBLOCK, &s, NULL); pthread_sigmask(SIG_UNBLOCK, &s, NULL);
sigset(THR_SERVER_ALARM,process_alarm);
#endif #endif
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -290,7 +280,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) ...@@ -290,7 +280,7 @@ sig_handler process_alarm(int sig __attribute__((unused)))
printf("thread_alarm\n"); fflush(stdout); printf("thread_alarm\n"); fflush(stdout);
#endif #endif
#ifdef DONT_REMEMBER_SIGNAL #ifdef DONT_REMEMBER_SIGNAL
sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ my_sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */
#endif #endif
return; return;
} }
...@@ -310,7 +300,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) ...@@ -310,7 +300,7 @@ sig_handler process_alarm(int sig __attribute__((unused)))
process_alarm_part2(sig); process_alarm_part2(sig);
#ifndef USE_ALARM_THREAD #ifndef USE_ALARM_THREAD
#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) #if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND)
sigset(THR_SERVER_ALARM,process_alarm); my_sigset(THR_SERVER_ALARM,process_alarm);
#endif #endif
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL); pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
...@@ -512,7 +502,7 @@ static sig_handler thread_alarm(int sig) ...@@ -512,7 +502,7 @@ static sig_handler thread_alarm(int sig)
printf("thread_alarm\n"); fflush(stdout); printf("thread_alarm\n"); fflush(stdout);
#endif #endif
#ifdef DONT_REMEMBER_SIGNAL #ifdef DONT_REMEMBER_SIGNAL
sigset(sig,thread_alarm); /* int. thread system calls */ my_sigset(sig,thread_alarm); /* int. thread system calls */
#endif #endif
} }
#endif #endif
...@@ -916,7 +906,7 @@ static sig_handler print_signal_warning(int sig) ...@@ -916,7 +906,7 @@ static sig_handler print_signal_warning(int sig)
printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name());
fflush(stdout); fflush(stdout);
#ifdef DONT_REMEMBER_SIGNAL #ifdef DONT_REMEMBER_SIGNAL
sigset(sig,print_signal_warning); /* int. thread system calls */ my_sigset(sig,print_signal_warning); /* int. thread system calls */
#endif #endif
#ifndef OS2 #ifndef OS2
if (sig == SIGALRM) if (sig == SIGALRM)
......
...@@ -846,7 +846,7 @@ static void __cdecl kill_server(int sig_ptr) ...@@ -846,7 +846,7 @@ static void __cdecl kill_server(int sig_ptr)
RETURN_FROM_KILL_SERVER; RETURN_FROM_KILL_SERVER;
kill_in_progress=TRUE; kill_in_progress=TRUE;
abort_loop=1; // This should be set abort_loop=1; // This should be set
signal(sig,SIG_IGN); my_sigset(sig,SIG_IGN);
if (sig == MYSQL_KILL_SIGNAL || sig == 0) if (sig == MYSQL_KILL_SIGNAL || sig == 0)
sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname); sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname);
else else
...@@ -894,11 +894,6 @@ extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused))) ...@@ -894,11 +894,6 @@ extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
} }
#endif #endif
#if defined(__amiga__)
#undef sigset
#define sigset signal
#endif
extern "C" sig_handler print_signal_warning(int sig) extern "C" sig_handler print_signal_warning(int sig)
{ {
if (!DBUG_IN_USE) if (!DBUG_IN_USE)
...@@ -908,7 +903,7 @@ extern "C" sig_handler print_signal_warning(int sig) ...@@ -908,7 +903,7 @@ extern "C" sig_handler print_signal_warning(int sig)
sig,my_thread_id()); sig,my_thread_id());
} }
#ifdef DONT_REMEMBER_SIGNAL #ifdef DONT_REMEMBER_SIGNAL
sigset(sig,print_signal_warning); /* int. thread system calls */ my_sigset(sig,print_signal_warning); /* int. thread system calls */
#endif #endif
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
if (sig == SIGALRM) if (sig == SIGALRM)
...@@ -1570,23 +1565,6 @@ void flush_thread_cache() ...@@ -1570,23 +1565,6 @@ void flush_thread_cache()
} }
/*
Aborts a thread nicely. Commes here on SIGPIPE
TODO: One should have to fix that thr_alarm know about this
thread too.
*/
#ifdef THREAD_SPECIFIC_SIGPIPE
extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("abort_thread");
if (thd)
thd->killed=1;
DBUG_VOID_RETURN;
}
#endif
/****************************************************************************** /******************************************************************************
Setup a signal thread with handles all signals. Setup a signal thread with handles all signals.
Because Linux doesn't support schemas use a mutex to check that Because Linux doesn't support schemas use a mutex to check that
...@@ -2002,8 +1980,8 @@ static void init_signals(void) ...@@ -2002,8 +1980,8 @@ static void init_signals(void)
DBUG_ENTER("init_signals"); DBUG_ENTER("init_signals");
if (test_flags & TEST_SIGINT) if (test_flags & TEST_SIGINT)
sigset(THR_KILL_SIGNAL,end_thread_signal); my_sigset(THR_KILL_SIGNAL,end_thread_signal);
sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
{ {
...@@ -2037,13 +2015,8 @@ static void init_signals(void) ...@@ -2037,13 +2015,8 @@ static void init_signals(void)
} }
#endif #endif
(void) sigemptyset(&set); (void) sigemptyset(&set);
#ifdef THREAD_SPECIFIC_SIGPIPE my_sigset(SIGPIPE,SIG_IGN);
sigset(SIGPIPE,abort_thread);
sigaddset(&set,SIGPIPE);
#else
(void) signal(SIGPIPE,SIG_IGN); // Can't know which thread
sigaddset(&set,SIGPIPE); sigaddset(&set,SIGPIPE);
#endif
sigaddset(&set,SIGINT); sigaddset(&set,SIGINT);
#ifndef IGNORE_SIGHUP_SIGQUIT #ifndef IGNORE_SIGHUP_SIGQUIT
sigaddset(&set,SIGQUIT); sigaddset(&set,SIGQUIT);
......
...@@ -136,10 +136,18 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost) ...@@ -136,10 +136,18 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
vio->sd); vio->sd);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
#if !defined(NO_FCNTL_NONBLOCK) #if !defined(NO_FCNTL_NONBLOCK)
#if defined(__FreeBSD__) /*
fcntl(sd, F_SETFL, vio->fcntl_mode); /* Yahoo! FreeBSD patch */ We call fcntl() to set the flags and then immediately read them back
#endif to make sure that we and the system are in agreement on the state of
vio->fcntl_mode = fcntl(sd, F_GETFL); things.
An example of why we need to do this is FreeBSD (and apparently some
other BSD-derived systems, like Mac OS X), where the system sometimes
reports that the socket is set for non-blocking when it really will
block.
*/
fcntl(sd, F_SETFL, vio->fcntl_mode);
vio->fcntl_mode= fcntl(sd, F_GETFL);
#elif defined(HAVE_SYS_IOCTL_H) /* hpux */ #elif defined(HAVE_SYS_IOCTL_H) /* hpux */
/* Non blocking sockets doesn't work good on HPUX 11.0 */ /* Non blocking sockets doesn't work good on HPUX 11.0 */
(void) ioctl(sd,FIOSNBIO,0); (void) ioctl(sd,FIOSNBIO,0);
......
...@@ -92,7 +92,14 @@ int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode, ...@@ -92,7 +92,14 @@ int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
else else
vio->fcntl_mode |= O_NONBLOCK; /* set bit */ vio->fcntl_mode |= O_NONBLOCK; /* set bit */
if (old_fcntl != vio->fcntl_mode) if (old_fcntl != vio->fcntl_mode)
r = fcntl(vio->sd, F_SETFL, vio->fcntl_mode); {
r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
if (r == -1)
{
DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
vio->fcntl_mode= old_fcntl;
}
}
} }
#else #else
r= set_blocking_mode ? 0 : 1; r= set_blocking_mode ? 0 : 1;
......
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