backport of shutdown fix for platforms that cannot break a syscall with a

signal. Tested to the extent that it does not break Linux. Could not test on
Darwin because the machine was not reachable. Will push anyway - at least it
does not make things worse. Testing on Darwin is needed, however.
parent e8b45861
...@@ -40,6 +40,11 @@ ...@@ -40,6 +40,11 @@
#define ONE_THREAD #define ONE_THREAD
#endif #endif
#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
#define HAVE_CLOSE_SERVER_SOCK 1
void close_server_sock();
#endif
extern "C" { // Because of SCO 3.2V4.2 extern "C" { // Because of SCO 3.2V4.2
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -442,16 +447,7 @@ static void close_connections(void) ...@@ -442,16 +447,7 @@ static void close_connections(void)
sql_print_error("Got error %d from pthread_cond_timedwait",error); sql_print_error("Got error %d from pthread_cond_timedwait",error);
#endif #endif
#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) #if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
if (ip_sock != INVALID_SOCKET) close_server_sock();
{
DBUG_PRINT("error",("closing TCP/IP and socket files"));
VOID(shutdown(ip_sock,2));
VOID(closesocket(ip_sock));
VOID(shutdown(unix_sock,2));
VOID(closesocket(unix_sock));
VOID(unlink(mysql_unix_port));
ip_sock=unix_sock= INVALID_SOCKET;
}
#endif #endif
} }
(void) pthread_mutex_unlock(&LOCK_thread_count); (void) pthread_mutex_unlock(&LOCK_thread_count);
...@@ -566,10 +562,35 @@ static void close_connections(void) ...@@ -566,10 +562,35 @@ static void close_connections(void)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#ifdef HAVE_CLOSE_SERVER_SOCK
void close_server_sock()
{
DBUG_ENTER("close_server_sock");
if (ip_sock != INVALID_SOCKET)
{
DBUG_PRINT("info",("closing TCP/IP socket"));
VOID(shutdown(ip_sock,2));
VOID(closesocket(ip_sock));
ip_sock=INVALID_SOCKET;
}
if (unix_sock != INVALID_SOCKET)
{
DBUG_PRINT("info",("closing Unix socket"));
VOID(shutdown(unix_sock,2));
VOID(closesocket(unix_sock));
VOID(unlink(mysql_unix_port));
unix_sock=INVALID_SOCKET;
}
DBUG_VOID_RETURN;
}
#endif
void kill_mysql(void) void kill_mysql(void)
{ {
DBUG_ENTER("kill_mysql"); DBUG_ENTER("kill_mysql");
#ifdef SIGNALS_DONT_BREAK_READ
close_server_sock(); /* force accept to wake up */
#endif
#if defined(__WIN__) #if defined(__WIN__)
{ {
if (!SetEvent(hEventShutdown)) if (!SetEvent(hEventShutdown))
...@@ -593,6 +614,9 @@ void kill_mysql(void) ...@@ -593,6 +614,9 @@ void kill_mysql(void)
#endif #endif
DBUG_PRINT("quit",("After pthread_kill")); DBUG_PRINT("quit",("After pthread_kill"));
shutdown_in_progress=1; // Safety if kill didn't work shutdown_in_progress=1; // Safety if kill didn't work
#ifdef SIGNALS_DONT_BREAK_READ
abort_loop=1;
#endif
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -1049,6 +1073,20 @@ void end_thread(THD *thd, bool put_in_cache) ...@@ -1049,6 +1073,20 @@ void end_thread(THD *thd, bool put_in_cache)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#ifdef SIGNALS_DONT_BREAK_READ
inline void kill_broken_server()
{
/* hack to get around signals ignored in syscalls for problem OS's */
if (unix_sock == INVALID_SOCKET || ip_sock ==INVALID_SOCKET)
{
select_thread_in_use = 0;
kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
}
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
#else
#define MAYBE_BROKEN_SYSCALL
#endif
/* Start a cached thread. LOCK_thread_count is locked on entry */ /* Start a cached thread. LOCK_thread_count is locked on entry */
...@@ -2251,6 +2289,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) ...@@ -2251,6 +2289,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
#endif #endif
DBUG_PRINT("general",("Waiting for connections.")); DBUG_PRINT("general",("Waiting for connections."));
MAYBE_BROKEN_SYSCALL;
while (!abort_loop) while (!abort_loop)
{ {
readFDs=clientFDs; readFDs=clientFDs;
...@@ -2265,6 +2304,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) ...@@ -2265,6 +2304,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
if (!select_errors++ && !abort_loop) /* purecov: inspected */ if (!select_errors++ && !abort_loop) /* purecov: inspected */
sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */ sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
} }
MAYBE_BROKEN_SYSCALL;
continue; continue;
} }
#endif /* HPUX */ #endif /* HPUX */
...@@ -2306,6 +2346,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) ...@@ -2306,6 +2346,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
if (new_sock != INVALID_SOCKET || if (new_sock != INVALID_SOCKET ||
(socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN)) (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
break; break;
MAYBE_BROKEN_SYSCALL;
#if !defined(NO_FCNTL_NONBLOCK) #if !defined(NO_FCNTL_NONBLOCK)
if (!(test_flags & TEST_BLOCKING)) if (!(test_flags & TEST_BLOCKING))
{ {
...@@ -2322,6 +2363,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) ...@@ -2322,6 +2363,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
{ {
if ((error_count++ & 255) == 0) // This can happen often if ((error_count++ & 255) == 0) // This can happen often
sql_perror("Error in accept"); sql_perror("Error in accept");
MAYBE_BROKEN_SYSCALL;
if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE) if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
sleep(1); // Give other threads some time sleep(1); // Give other threads some time
continue; continue;
......
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