BUG#13431369 - MAIN.VARIABLES-NOTEMBEDDED CRASHES THE SERVER SPORADICALLY ON WINDOWS

On shutdown(), Windows can drop traffic still queued for sending even if that
wasn't specifically requested. As a result, fatal errors (those after
signaling which the server will drop the connection) were sometimes only
seen as "connection lost" on the client side, because the server-side
shutdown() erraneously discarded the correct error message before sending
it.

If on Windows, we now use the Windows API to access the (non-broken) equivalent
of shutdown().

Backport from trunk

include/violite.h:
  export mysql_socket_shutdown(). It lives in vio in the backport.
sql/mysqld.cc:
  Go through our own shutdown() rather than straight to the POSIX one.
vio/viosocket.c:
  Define mysql_socket_shutdown(). On UNIXoid systems, it's just a wrapper for shutdown(), but
  on Window, it uses DisconnectEx, which is magic.
parent d79058ca
...@@ -61,6 +61,9 @@ int vio_close_pipe(Vio * vio); ...@@ -61,6 +61,9 @@ int vio_close_pipe(Vio * vio);
#define HANDLE void * #define HANDLE void *
#endif /* __WIN__ */ #endif /* __WIN__ */
/* backport from 5.6 where it is part of PSI, not vio_*() */
int mysql_socket_shutdown(my_socket mysql_socket, int how);
void vio_delete(Vio* vio); void vio_delete(Vio* vio);
int vio_close(Vio* vio); int vio_close(Vio* vio);
void vio_reset(Vio* vio, enum enum_vio_type type, void vio_reset(Vio* vio, enum enum_vio_type type,
......
...@@ -932,7 +932,7 @@ static void close_connections(void) ...@@ -932,7 +932,7 @@ static void close_connections(void)
{ {
if (ip_sock != INVALID_SOCKET) if (ip_sock != INVALID_SOCKET)
{ {
(void) shutdown(ip_sock, SHUT_RDWR); (void) mysql_socket_shutdown(ip_sock, SHUT_RDWR);
(void) closesocket(ip_sock); (void) closesocket(ip_sock);
ip_sock= INVALID_SOCKET; ip_sock= INVALID_SOCKET;
} }
...@@ -964,7 +964,7 @@ static void close_connections(void) ...@@ -964,7 +964,7 @@ static void close_connections(void)
#ifdef HAVE_SYS_UN_H #ifdef HAVE_SYS_UN_H
if (unix_sock != INVALID_SOCKET) if (unix_sock != INVALID_SOCKET)
{ {
(void) shutdown(unix_sock, SHUT_RDWR); (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR);
(void) closesocket(unix_sock); (void) closesocket(unix_sock);
(void) unlink(mysqld_unix_port); (void) unlink(mysqld_unix_port);
unix_sock= INVALID_SOCKET; unix_sock= INVALID_SOCKET;
...@@ -1069,7 +1069,7 @@ static void close_server_sock() ...@@ -1069,7 +1069,7 @@ static void close_server_sock()
{ {
ip_sock=INVALID_SOCKET; ip_sock=INVALID_SOCKET;
DBUG_PRINT("info",("calling shutdown on TCP/IP socket")); DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
VOID(shutdown(tmp_sock, SHUT_RDWR)); VOID(mysql_socket_shutdown(tmp_sock, SHUT_RDWR));
#if defined(__NETWARE__) #if defined(__NETWARE__)
/* /*
The following code is disabled for normal systems as it causes MySQL The following code is disabled for normal systems as it causes MySQL
...@@ -1084,7 +1084,7 @@ static void close_server_sock() ...@@ -1084,7 +1084,7 @@ static void close_server_sock()
{ {
unix_sock=INVALID_SOCKET; unix_sock=INVALID_SOCKET;
DBUG_PRINT("info",("calling shutdown on unix socket")); DBUG_PRINT("info",("calling shutdown on unix socket"));
VOID(shutdown(tmp_sock, SHUT_RDWR)); VOID(mysql_socket_shutdown(tmp_sock, SHUT_RDWR));
#if defined(__NETWARE__) #if defined(__NETWARE__)
/* /*
The following code is disabled for normal systems as it may cause MySQL The following code is disabled for normal systems as it may cause MySQL
...@@ -5091,7 +5091,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) ...@@ -5091,7 +5091,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
if (req.sink) if (req.sink)
((void (*)(int))req.sink)(req.fd); ((void (*)(int))req.sink)(req.fd);
(void) shutdown(new_sock, SHUT_RDWR); (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
(void) closesocket(new_sock); (void) closesocket(new_sock);
continue; continue;
} }
...@@ -5106,7 +5106,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) ...@@ -5106,7 +5106,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
if (getsockname(new_sock,&dummy, &dummyLen) < 0) if (getsockname(new_sock,&dummy, &dummyLen) < 0)
{ {
sql_perror("Error on new connection socket"); sql_perror("Error on new connection socket");
(void) shutdown(new_sock, SHUT_RDWR); (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
(void) closesocket(new_sock); (void) closesocket(new_sock);
continue; continue;
} }
...@@ -5118,7 +5118,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) ...@@ -5118,7 +5118,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
if (!(thd= new THD)) if (!(thd= new THD))
{ {
(void) shutdown(new_sock, SHUT_RDWR); (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
VOID(closesocket(new_sock)); VOID(closesocket(new_sock));
continue; continue;
} }
...@@ -5137,7 +5137,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) ...@@ -5137,7 +5137,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
vio_delete(vio_tmp); vio_delete(vio_tmp);
else else
{ {
(void) shutdown(new_sock, SHUT_RDWR); (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
(void) closesocket(new_sock); (void) closesocket(new_sock);
} }
delete thd; delete thd;
......
...@@ -23,8 +23,15 @@ ...@@ -23,8 +23,15 @@
the file descriptior. the file descriptior.
*/ */
#ifdef __WIN__
#include <winsock2.h>
#include <MSWSock.h>
#pragma comment(lib, "ws2_32.lib")
#endif
#include "vio_priv.h" #include "vio_priv.h"
int vio_errno(Vio *vio __attribute__((unused))) int vio_errno(Vio *vio __attribute__((unused)))
{ {
return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
...@@ -260,6 +267,37 @@ vio_was_interrupted(Vio *vio __attribute__((unused))) ...@@ -260,6 +267,37 @@ vio_was_interrupted(Vio *vio __attribute__((unused)))
} }
int
mysql_socket_shutdown(my_socket mysql_socket, int how)
{
int result;
#ifdef __WIN__
static LPFN_DISCONNECTEX DisconnectEx = NULL;
if (DisconnectEx == NULL)
{
DWORD dwBytesReturned;
GUID guidDisconnectEx = WSAID_DISCONNECTEX;
WSAIoctl(mysql_socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidDisconnectEx, sizeof(GUID),
&DisconnectEx, sizeof(DisconnectEx),
&dwBytesReturned, NULL, NULL);
}
#endif
/* Non instrumented code */
#ifdef __WIN__
if (DisconnectEx)
result= (DisconnectEx(mysql_socket, (LPOVERLAPPED) NULL,
(DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
else
#endif
result= shutdown(mysql_socket, how);
return result;
}
int vio_close(Vio * vio) int vio_close(Vio * vio)
{ {
int r=0; int r=0;
...@@ -272,7 +310,7 @@ int vio_close(Vio * vio) ...@@ -272,7 +310,7 @@ int vio_close(Vio * vio)
vio->type == VIO_TYPE_SSL); vio->type == VIO_TYPE_SSL);
DBUG_ASSERT(vio->sd >= 0); DBUG_ASSERT(vio->sd >= 0);
if (shutdown(vio->sd, SHUT_RDWR)) if (mysql_socket_shutdown(vio->sd, SHUT_RDWR))
r= -1; r= -1;
if (closesocket(vio->sd)) if (closesocket(vio->sd))
r= -1; r= -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