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. mysql-test/r/shm.result: Add test case result for Bug#33899 mysql-test/t/shm.test: Add test case for Bug#33899 vio/viosocket.c: Also wait for close events.
This commit is contained in:
parent
4ee0f6a64c
commit
96e02e5716
@ -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'`){
|
|||||||
#
|
#
|
||||||
--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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user