Commit bfa198c2 authored by Davi Arnaut's avatar Davi Arnaut

Bug#33899: Deadlock in mysql_real_query with shared memory connections

The problem is that the read and write methods of the shared
memory transport (protocol) didn't react to asynchronous close
events, which could lead to a lock up as the client would wait
(until time out) for a server response that will never come.

The solution is to also wait for close events while waiting
for I/O from or to the server.
parent 1517db6b
...@@ -2152,4 +2152,11 @@ Warnings: ...@@ -2152,4 +2152,11 @@ Warnings:
Warning 1052 Column 'kundentyp' in group statement is ambiguous Warning 1052 Column 'kundentyp' in group statement is ambiguous
drop table t1; drop table t1;
mysqld is alive mysqld is alive
SET @max_allowed_packet= @@global.max_allowed_packet;
SET @net_buffer_length= @@global.net_buffer_length;
SET GLOBAL max_allowed_packet= 1024;
SET GLOBAL net_buffer_length= 1024;
ERROR 1153 (08S01) at line 1: Got a packet bigger than 'max_allowed_packet' bytes
SET GLOBAL max_allowed_packet= @max_allowed_packet;
SET GLOBAL net_buffer_length= @net_buffer_length;
End of 5.0 tests. End of 5.0 tests.
...@@ -16,4 +16,23 @@ if (`SELECT '$shm' != 'ON'`){ ...@@ -16,4 +16,23 @@ if (`SELECT '$shm' != 'ON'`){
# #
--exec $MYSQLADMIN --no-defaults --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --shared-memory-base-name=HeyMrBaseNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ping --exec $MYSQLADMIN --no-defaults --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --shared-memory-base-name=HeyMrBaseNameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ping
#
# Bug #33899: Deadlock in mysql_real_query with shared memory connections
#
let $name= query_get_value("SHOW GLOBAL VARIABLES LIKE 'shared_memory_base_name'", Value, 1);
let $stmt= `SELECT REPEAT('a', 2048)`;
SET @max_allowed_packet= @@global.max_allowed_packet;
SET @net_buffer_length= @@global.net_buffer_length;
SET GLOBAL max_allowed_packet= 1024;
SET GLOBAL net_buffer_length= 1024;
--error 1
--exec echo SELECT '$stmt'| $MYSQL --protocol=memory --shared-memory-base-name=$name 2>&1
SET GLOBAL max_allowed_packet= @max_allowed_packet;
SET GLOBAL net_buffer_length= @net_buffer_length;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -479,26 +479,28 @@ int vio_read_shared_memory(Vio * vio, gptr buf, int size) ...@@ -479,26 +479,28 @@ int vio_read_shared_memory(Vio * vio, gptr buf, int size)
int length; int length;
int remain_local; int remain_local;
char *current_postion; char *current_postion;
HANDLE events[2];
DBUG_ENTER("vio_read_shared_memory"); DBUG_ENTER("vio_read_shared_memory");
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
remain_local = size; remain_local = size;
current_postion=buf; current_postion=buf;
events[0]= vio->event_server_wrote;
events[1]= vio->event_conn_closed;
do do
{ {
if (vio->shared_memory_remain == 0) if (vio->shared_memory_remain == 0)
{ {
HANDLE events[2];
events[0]= vio->event_server_wrote;
events[1]= vio->event_conn_closed;
/* /*
WaitForMultipleObjects can return next values: WaitForMultipleObjects can return next values:
WAIT_OBJECT_0+0 - event from vio->event_server_wrote WAIT_OBJECT_0+0 - event from vio->event_server_wrote
WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything
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(2, (HANDLE*)&events,FALSE, if (WaitForMultipleObjects(array_elements(events), events, FALSE,
vio->net->read_timeout*1000) != WAIT_OBJECT_0) vio->net->read_timeout*1000) != WAIT_OBJECT_0)
{ {
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -537,19 +539,23 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size) ...@@ -537,19 +539,23 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
{ {
int length; int length;
uint remain; uint remain;
HANDLE pos;
int sz; int sz;
char *current_postion; char *current_postion;
HANDLE pos, events[2];
DBUG_ENTER("vio_write_shared_memory"); DBUG_ENTER("vio_write_shared_memory");
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
remain = size; remain = size;
current_postion = buf; current_postion = buf;
events[0]= vio->event_server_read;
events[1]= vio->event_conn_closed;
while (remain != 0) while (remain != 0)
{ {
if (WaitForSingleObject(vio->event_server_read, vio->net->write_timeout*1000) if (WaitForMultipleObjects(array_elements(events), events, FALSE,
!= WAIT_OBJECT_0) vio->net->write_timeout*1000) != WAIT_OBJECT_0)
{ {
DBUG_RETURN(-1); DBUG_RETURN(-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