From: Jim Winstead Date: October 11 2005 4:12pm Subject: bk commit into 4.1 tree (jimw:1.2477) BUG#8731 List-Archive: http://lists.mysql.com/internals/30925 X-Bug: 8731 Message-Id: <20051011161217.30B69A837B@rama.trainedmonkey.com> Below is the list of changes that have just been committed into a local 4.1 repository of jimw. When jimw does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2477 05/10/11 09:12:12 jimw@stripped +11 -0 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) mysql-test/t/wait_timeout.test 1.1 05/10/11 09:12:10 jimw@stripped +11 -0 New BitKeeper file ``mysql-test/t/wait_timeout.test'' mysql-test/t/wait_timeout-master.opt 1.1 05/10/11 09:12:10 jimw@stripped +1 -0 New BitKeeper file ``mysql-test/t/wait_timeout-master.opt'' mysql-test/r/wait_timeout.result 1.1 05/10/11 09:12:10 jimw@stripped +8 -0 New BitKeeper file ``mysql-test/r/wait_timeout.result'' vio/viosocket.c 1.35 05/10/11 09:12:10 jimw@stripped +8 -1 If fcntl() fails in vio_blocking(), restore the flags stored in the vio struct. vio/vio.c 1.23 05/10/11 09:12:10 jimw@stripped +12 -4 Always call fcntl() to initialize flags of socket in initialization to avoid problems on systems that don't report the flags on a socket correctly right after it has been returned from accept(), such as FreeBSD, Mac OS X, and possibly other BSD-derived systems. mysql-test/t/wait_timeout.test 1.0 05/10/11 09:12:10 jimw@stripped +0 -0 BitKeeper file /home/jimw/my/mysql-4.1-8731b/mysql-test/t/wait_timeout.test mysql-test/t/wait_timeout-master.opt 1.0 05/10/11 09:12:10 jimw@stripped +0 -0 BitKeeper file /home/jimw/my/mysql-4.1-8731b/mysql-test/t/wait_timeout-master.opt mysql-test/r/wait_timeout.result 1.0 05/10/11 09:12:10 jimw@stripped +0 -0 BitKeeper file /home/jimw/my/mysql-4.1-8731b/mysql-test/r/wait_timeout.result sql/mysqld.cc 1.603 05/10/11 09:12:09 jimw@stripped +5 -32 Use my_sigset() instead of signal() and sigset(), remove unnecessary definition of sigset on __amiga__. Remove unused THREAD_SPECIFIC_SIGPIPE code. A future improvement would be to re-assess the use of sigaction() here and convert its usage to use my_sigset(). mysys/thr_alarm.c 1.46 05/10/11 09:12:09 jimw@stripped +7 -17 Use my_sigset() instead of sigset(). mysys/my_pthread.c 1.43 05/10/11 09:12:09 jimw@stripped +0 -17 Remove pthread_signal(), which is identical to the new my_sigset() macro. include/my_pthread.h 1.81 05/10/11 09:12:09 jimw@stripped +21 -14 Define my_sigset() instead of trying to monkey with sigset(), and favor an implementation based on sigaction(). include/config-win.h 1.55 05/10/11 09:12:09 jimw@stripped +1 -1 Define my_sigset() instead of sigset(). configure.in 1.396 05/10/11 09:12:09 jimw@stripped +3 -13 Fix flags for Darwin 6 and later. Simplify Darwin 7-9 blocks to simply be a catch-all for *darwin* so that future Darwin releases get the latest flags. # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: jimw # Host: rama.(none) # Root: /home/jimw/my/mysql-4.1-8731b --- 1.395/configure.in 2005-09-13 11:46:53 -07:00 +++ 1.396/configure.in 2005-10-11 09:12:09 -07:00 @@ -1102,7 +1102,7 @@ *darwin5*) if test "$ac_cv_prog_gcc" = "yes" 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" CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" @@ -1112,23 +1112,13 @@ *darwin6*) if test "$ac_cv_prog_gcc" = "yes" 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" CXXFLAGS="$CXXFLAGS $FLAGS" MAX_C_OPTIMIZE="-O" fi ;; - *darwin[[7-8]]*) - # 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*) + *darwin*) if test "$ac_cv_prog_gcc" = "yes" then FLAGS="-D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT" --- 1.54/include/config-win.h 2005-07-29 05:51:02 -07:00 +++ 1.55/include/config-win.h 2005-10-11 09:12:09 -07:00 @@ -192,7 +192,7 @@ /* 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 sleep(A) Sleep((A)*1000) #define popen(A) popen(A,B) _popen((A),(B)) --- 1.80/include/my_pthread.h 2005-09-12 10:19:53 -07:00 +++ 1.81/include/my_pthread.h 2005-10-11 09:12:09 -07:00 @@ -289,8 +289,6 @@ #undef HAVE_PTHREAD_RWLOCK_RDLOCK #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) #endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ @@ -322,14 +320,26 @@ #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 */ #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); \ - s.sa_mask = set; \ - s.sa_flags = 0; \ - sigaction((A), &s, (struct sigaction *) NULL); \ - } while (0) + + +/* + We define my_sigset() and use that instead of the system sigset() so that + we can favor an implementation based on sigaction(). On some systems, such + as Mac OS X, sigset() results in flags such as SA_RESTART being set, and + we want to make sure that no such flags are set. +*/ +#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 #ifndef my_pthread_setprio @@ -409,16 +419,13 @@ #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } #endif -#ifdef HAVE_DARWIN_THREADS +#ifdef HAVE_DARWIN5_THREADS #define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C)) #define pthread_kill(A,B) pthread_dummy(0) #define pthread_condattr_init(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 #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 #if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER) --- 1.42/mysys/my_pthread.c 2004-06-10 12:58:36 -07:00 +++ 1.43/mysys/my_pthread.c 2005-10-11 09:12:09 -07:00 @@ -404,23 +404,6 @@ #endif /* DONT_USE_SIGSUSPEND */ #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 --- 1.45/mysys/thr_alarm.c 2005-06-28 05:06:11 -07:00 +++ 1.46/mysys/thr_alarm.c 2005-10-11 09:12:09 -07:00 @@ -80,17 +80,7 @@ pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_alarm,NULL); #if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD) -#if defined(HAVE_mit_thread) - 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 + my_sigset(THR_CLIENT_ALARM,thread_alarm); #endif sigemptyset(&s); sigaddset(&s, THR_SERVER_ALARM); @@ -110,12 +100,12 @@ #elif defined(USE_ONE_SIGNAL_HAND) pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ #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); #endif #else + my_sigset(THR_SERVER_ALARM, process_alarm); pthread_sigmask(SIG_UNBLOCK, &s, NULL); - sigset(THR_SERVER_ALARM,process_alarm); #endif DBUG_VOID_RETURN; } @@ -290,7 +280,7 @@ printf("thread_alarm\n"); fflush(stdout); #endif #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 return; } @@ -310,7 +300,7 @@ process_alarm_part2(sig); #ifndef USE_ALARM_THREAD #if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) - sigset(THR_SERVER_ALARM,process_alarm); + my_sigset(THR_SERVER_ALARM,process_alarm); #endif pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); @@ -512,7 +502,7 @@ printf("thread_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL - sigset(sig,thread_alarm); /* int. thread system calls */ + my_sigset(sig,thread_alarm); /* int. thread system calls */ #endif } #endif @@ -916,7 +906,7 @@ printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); fflush(stdout); #ifdef DONT_REMEMBER_SIGNAL - sigset(sig,print_signal_warning); /* int. thread system calls */ + my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif #ifndef OS2 if (sig == SIGALRM) --- 1.602/sql/mysqld.cc 2005-09-28 17:07:38 -07:00 +++ 1.603/sql/mysqld.cc 2005-10-11 09:12:09 -07:00 @@ -846,7 +846,7 @@ RETURN_FROM_KILL_SERVER; kill_in_progress=TRUE; abort_loop=1; // This should be set - signal(sig,SIG_IGN); + my_sigset(sig,SIG_IGN); if (sig == MYSQL_KILL_SIGNAL || sig == 0) sql_print_information(ER(ER_NORMAL_SHUTDOWN),my_progname); else @@ -894,11 +894,6 @@ } #endif -#if defined(__amiga__) -#undef sigset -#define sigset signal -#endif - extern "C" sig_handler print_signal_warning(int sig) { if (!DBUG_IN_USE) @@ -908,7 +903,7 @@ sig,my_thread_id()); } #ifdef DONT_REMEMBER_SIGNAL - sigset(sig,print_signal_warning); /* int. thread system calls */ + my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) if (sig == SIGALRM) @@ -1570,23 +1565,6 @@ } -/* - 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. Because Linux doesn't support schemas use a mutex to check that @@ -2002,8 +1980,8 @@ DBUG_ENTER("init_signals"); if (test_flags & TEST_SIGINT) - sigset(THR_KILL_SIGNAL,end_thread_signal); - sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! + my_sigset(THR_KILL_SIGNAL,end_thread_signal); + my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called! if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) { @@ -2037,13 +2015,8 @@ } #endif (void) sigemptyset(&set); -#ifdef THREAD_SPECIFIC_SIGPIPE - sigset(SIGPIPE,abort_thread); - sigaddset(&set,SIGPIPE); -#else - (void) signal(SIGPIPE,SIG_IGN); // Can't know which thread + my_sigset(SIGPIPE,SIG_IGN); sigaddset(&set,SIGPIPE); -#endif sigaddset(&set,SIGINT); #ifndef IGNORE_SIGHUP_SIGQUIT sigaddset(&set,SIGQUIT); --- New file --- +++ mysql-test/r/wait_timeout.result 05/10/11 09:12:10 select 1; 1 1 select 2; ERROR HY000: MySQL server has gone away select 3; 3 3 --- New file --- +++ mysql-test/t/wait_timeout-master.opt 05/10/11 09:12:10 --wait-timeout=2 --- New file --- +++ mysql-test/t/wait_timeout.test 05/10/11 09:12:10 # # 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; --- 1.22/vio/vio.c 2005-09-07 04:57:05 -07:00 +++ 1.23/vio/vio.c 2005-10-11 09:12:10 -07:00 @@ -136,10 +136,18 @@ vio->sd); #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) #if !defined(NO_FCNTL_NONBLOCK) -#if defined(__FreeBSD__) - fcntl(sd, F_SETFL, vio->fcntl_mode); /* Yahoo! FreeBSD patch */ -#endif - vio->fcntl_mode = fcntl(sd, F_GETFL); + /* + We call fcntl() to set the flags and then immediately read them back + to make sure that we and the system are in agreement on the state of + 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 */ /* Non blocking sockets doesn't work good on HPUX 11.0 */ (void) ioctl(sd,FIOSNBIO,0); --- 1.34/vio/viosocket.c 2005-09-15 10:00:23 -07:00 +++ 1.35/vio/viosocket.c 2005-10-11 09:12:10 -07:00 @@ -92,7 +92,14 @@ else vio->fcntl_mode |= O_NONBLOCK; /* set bit */ 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 r= set_blocking_mode ? 0 : 1;