Commit 78da7343 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

Bug#47571 : idle named pipe connection is unkillable

implement Davi's review suggestions (post-push fixes)
parent 349f48e1
...@@ -224,8 +224,8 @@ struct st_vio ...@@ -224,8 +224,8 @@ struct st_vio
#endif /* HAVE_SMEM */ #endif /* HAVE_SMEM */
#ifdef _WIN32 #ifdef _WIN32
OVERLAPPED pipe_overlapped; OVERLAPPED pipe_overlapped;
DWORD read_timeout_millis; DWORD read_timeout_ms;
DWORD write_timeout_millis; DWORD write_timeout_ms;
#endif #endif
}; };
#endif /* vio_violite_h_ */ #endif /* vio_violite_h_ */
...@@ -5224,12 +5224,16 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) ...@@ -5224,12 +5224,16 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
pthread_handler_t handle_connections_namedpipes(void *arg) pthread_handler_t handle_connections_namedpipes(void *arg)
{ {
HANDLE hConnectedPipe; HANDLE hConnectedPipe;
OVERLAPPED connectOverlapped = {0}; OVERLAPPED connectOverlapped= {0};
THD *thd; THD *thd;
my_thread_init(); my_thread_init();
DBUG_ENTER("handle_connections_namedpipes"); DBUG_ENTER("handle_connections_namedpipes");
connectOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
if (!connectOverlapped.hEvent)
{
sql_print_error("Can't create event, last error=%u", GetLastError());
unireg_abort(1);
}
DBUG_PRINT("general",("Waiting for named pipe connections.")); DBUG_PRINT("general",("Waiting for named pipe connections."));
while (!abort_loop) while (!abort_loop)
{ {
...@@ -5252,7 +5256,8 @@ pthread_handler_t handle_connections_namedpipes(void *arg) ...@@ -5252,7 +5256,8 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
{ {
CloseHandle(hPipe); CloseHandle(hPipe);
if ((hPipe= CreateNamedPipe(pipe_name, if ((hPipe= CreateNamedPipe(pipe_name,
PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_ACCESS_DUPLEX |
FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_TYPE_BYTE |
PIPE_READMODE_BYTE | PIPE_READMODE_BYTE |
PIPE_WAIT, PIPE_WAIT,
...@@ -5272,7 +5277,8 @@ pthread_handler_t handle_connections_namedpipes(void *arg) ...@@ -5272,7 +5277,8 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
hConnectedPipe = hPipe; hConnectedPipe = hPipe;
/* create new pipe for new connection */ /* create new pipe for new connection */
if ((hPipe = CreateNamedPipe(pipe_name, if ((hPipe = CreateNamedPipe(pipe_name,
PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_ACCESS_DUPLEX |
FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_TYPE_BYTE |
PIPE_READMODE_BYTE | PIPE_READMODE_BYTE |
PIPE_WAIT, PIPE_WAIT,
......
...@@ -62,10 +62,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type, ...@@ -62,10 +62,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
vio->timeout=vio_win32_timeout; vio->timeout=vio_win32_timeout;
/* Set default timeout */ /* Set default timeout */
vio->read_timeout_millis = INFINITE; vio->read_timeout_ms= INFINITE;
vio->write_timeout_millis = INFINITE; vio->write_timeout_ms= INFINITE;
memset(&(vio->pipe_overlapped), 0, sizeof(OVERLAPPED));
vio->pipe_overlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); vio->pipe_overlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -90,8 +88,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type, ...@@ -90,8 +88,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
/* Currently, shared memory is on Windows only, hence the below is ok*/ /* Currently, shared memory is on Windows only, hence the below is ok*/
vio->timeout= vio_win32_timeout; vio->timeout= vio_win32_timeout;
/* Set default timeout */ /* Set default timeout */
vio->read_timeout_millis= INFINITE; vio->read_timeout_ms= INFINITE;
vio->write_timeout_millis= INFINITE; vio->write_timeout_ms= INFINITE;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#endif #endif
...@@ -115,22 +113,20 @@ static void vio_init(Vio* vio, enum enum_vio_type type, ...@@ -115,22 +113,20 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
{ vio->viodelete =vio_delete;
vio->viodelete =vio_delete; vio->vioerrno =vio_errno;
vio->vioerrno =vio_errno; vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read;
vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read; vio->write =vio_write;
vio->write =vio_write; vio->fastsend =vio_fastsend;
vio->fastsend =vio_fastsend; vio->viokeepalive =vio_keepalive;
vio->viokeepalive =vio_keepalive; vio->should_retry =vio_should_retry;
vio->should_retry =vio_should_retry; vio->was_interrupted=vio_was_interrupted;
vio->was_interrupted=vio_was_interrupted; vio->vioclose =vio_close;
vio->vioclose =vio_close; vio->peer_addr =vio_peer_addr;
vio->peer_addr =vio_peer_addr; vio->in_addr =vio_in_addr;
vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking;
vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking;
vio->is_blocking =vio_is_blocking; vio->timeout =vio_timeout;
vio->timeout =vio_timeout;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -415,14 +415,14 @@ void vio_timeout(Vio *vio, uint which, uint timeout) ...@@ -415,14 +415,14 @@ void vio_timeout(Vio *vio, uint which, uint timeout)
/* /*
Finish pending IO on pipe. Honor wait timeout Finish pending IO on pipe. Honor wait timeout
*/ */
static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_millis) static size_t pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_ms)
{ {
DWORD length; DWORD length;
DWORD ret; DWORD ret;
DBUG_ENTER("pipe_complete_io"); DBUG_ENTER("pipe_complete_io");
ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_millis); ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_ms);
/* /*
WaitForSingleObjects will normally return WAIT_OBJECT_O (success, IO completed) WaitForSingleObjects will normally return WAIT_OBJECT_O (success, IO completed)
or WAIT_TIMEOUT. or WAIT_TIMEOUT.
...@@ -431,14 +431,14 @@ static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_mill ...@@ -431,14 +431,14 @@ static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_mill
{ {
CancelIo(vio->hPipe); CancelIo(vio->hPipe);
DBUG_PRINT("error",("WaitForSingleObject() returned %d", ret)); DBUG_PRINT("error",("WaitForSingleObject() returned %d", ret));
DBUG_RETURN(-1); DBUG_RETURN((size_t)-1);
} }
if (!GetOverlappedResult(vio->hPipe,&(vio->pipe_overlapped),&length, FALSE)) if (!GetOverlappedResult(vio->hPipe,&(vio->pipe_overlapped),&length, FALSE))
{ {
DBUG_PRINT("error",("GetOverlappedResult() returned last error %d", DBUG_PRINT("error",("GetOverlappedResult() returned last error %d",
GetLastError())); GetLastError()));
DBUG_RETURN(-1); DBUG_RETURN((size_t)-1);
} }
DBUG_RETURN(length); DBUG_RETURN(length);
...@@ -448,12 +448,17 @@ static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_mill ...@@ -448,12 +448,17 @@ static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_mill
size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size) size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size)
{ {
DWORD bytes_read; DWORD bytes_read;
size_t retval;
DBUG_ENTER("vio_read_pipe"); DBUG_ENTER("vio_read_pipe");
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf,
(uint) size)); (uint) size));
if (!ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read, if (ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read,
&(vio->pipe_overlapped))) &(vio->pipe_overlapped)))
{
retval= bytes_read;
}
else
{ {
if (GetLastError() != ERROR_IO_PENDING) if (GetLastError() != ERROR_IO_PENDING)
{ {
...@@ -461,23 +466,28 @@ size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size) ...@@ -461,23 +466,28 @@ size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size)
GetLastError())); GetLastError()));
DBUG_RETURN((size_t)-1); DBUG_RETURN((size_t)-1);
} }
bytes_read= pipe_complete_io(vio, buf, size,vio->read_timeout_millis); retval= pipe_complete_io(vio, buf, size,vio->read_timeout_ms);
} }
DBUG_PRINT("exit", ("%d", bytes_read)); DBUG_PRINT("exit", ("%lld", (longlong)retval));
DBUG_RETURN(bytes_read); DBUG_RETURN(retval);
} }
size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
{ {
DWORD bytes_written; DWORD bytes_written;
size_t retval;
DBUG_ENTER("vio_write_pipe"); DBUG_ENTER("vio_write_pipe");
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf,
(uint) size)); (uint) size));
if (!WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written, if (WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written,
&(vio->pipe_overlapped))) &(vio->pipe_overlapped)))
{
retval= bytes_written;
}
else
{ {
if (GetLastError() != ERROR_IO_PENDING) if (GetLastError() != ERROR_IO_PENDING)
{ {
...@@ -485,12 +495,11 @@ size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) ...@@ -485,12 +495,11 @@ size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
GetLastError())); GetLastError()));
DBUG_RETURN((size_t)-1); DBUG_RETURN((size_t)-1);
} }
bytes_written = pipe_complete_io(vio, (char *)buf, size, retval= pipe_complete_io(vio, (char *)buf, size, vio->write_timeout_ms);
vio->write_timeout_millis);
} }
DBUG_PRINT("exit", ("%d", bytes_written)); DBUG_PRINT("exit", ("%lld", (longlong)retval));
DBUG_RETURN(bytes_written); DBUG_RETURN(retval);
} }
...@@ -515,21 +524,21 @@ int vio_close_pipe(Vio * vio) ...@@ -515,21 +524,21 @@ int vio_close_pipe(Vio * vio)
void vio_win32_timeout(Vio *vio, uint which , uint timeout_sec) void vio_win32_timeout(Vio *vio, uint which , uint timeout_sec)
{ {
DWORD timeout_millis; DWORD timeout_ms;
/* /*
Windows is measuring timeouts in milliseconds. Check for possible int Windows is measuring timeouts in milliseconds. Check for possible int
overflow. overflow.
*/ */
if (timeout_sec > UINT_MAX/1000) if (timeout_sec > UINT_MAX/1000)
timeout_millis= INFINITE; timeout_ms= INFINITE;
else else
timeout_millis= timeout_sec * 1000; timeout_ms= timeout_sec * 1000;
/* which == 1 means "write", which == 0 means "read".*/ /* which == 1 means "write", which == 0 means "read".*/
if(which) if(which)
vio->write_timeout_millis= timeout_millis; vio->write_timeout_ms= timeout_ms;
else else
vio->read_timeout_millis= timeout_millis; vio->read_timeout_ms= timeout_ms;
} }
...@@ -564,7 +573,7 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) ...@@ -564,7 +573,7 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size)
WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything
*/ */
if (WaitForMultipleObjects(array_elements(events), events, FALSE, if (WaitForMultipleObjects(array_elements(events), events, FALSE,
vio->read_timeout_millis) != WAIT_OBJECT_0) vio->read_timeout_ms) != WAIT_OBJECT_0)
{ {
DBUG_RETURN(-1); DBUG_RETURN(-1);
}; };
...@@ -621,7 +630,7 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) ...@@ -621,7 +630,7 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
while (remain != 0) while (remain != 0)
{ {
if (WaitForMultipleObjects(array_elements(events), events, FALSE, if (WaitForMultipleObjects(array_elements(events), events, FALSE,
vio->write_timeout_millis) != WAIT_OBJECT_0) vio->write_timeout_ms) != WAIT_OBJECT_0)
{ {
DBUG_RETURN((size_t) -1); DBUG_RETURN((size_t) -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