diff options
author | Davi Arnaut <Davi.Arnaut@Sun.COM> | 2009-03-26 20:25:10 -0300 |
---|---|---|
committer | Davi Arnaut <Davi.Arnaut@Sun.COM> | 2009-03-26 20:25:10 -0300 |
commit | 7c2612135f7c13e06819ea4be0e61d1283086b6a (patch) | |
tree | 263224e9efc11eab2f5fae7d03581c0e7a499a89 /vio | |
parent | 19e3c5c8e0b009a437f260da764cfc2cae501eba (diff) | |
parent | 96e02e57166a37f79c10f5f9afc1f9185e1110a7 (diff) | |
download | mariadb-git-7c2612135f7c13e06819ea4be0e61d1283086b6a.tar.gz |
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 asynchornous 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.
Bug report and patch submitted by: Armin Schöffmann
Diffstat (limited to 'vio')
-rw-r--r-- | vio/viosocket.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/vio/viosocket.c b/vio/viosocket.c index 942f0330c57..2d7fd0e08cd 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -480,19 +480,22 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) size_t length; size_t remain_local; char *current_postion; + HANDLE events[2]; + DBUG_ENTER("vio_read_shared_memory"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); remain_local = size; current_postion=buf; + + events[0]= vio->event_server_wrote; + events[1]= vio->event_conn_closed; + do { 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: WAIT_OBJECT_0+0 - event from vio->event_server_wrote @@ -500,7 +503,7 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) 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) { DBUG_RETURN(-1); @@ -543,17 +546,22 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) size_t length, remain, sz; HANDLE pos; const uchar *current_postion; + HANDLE events[2]; + DBUG_ENTER("vio_write_shared_memory"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); remain = size; current_postion = buf; + + events[0]= vio->event_server_read; + events[1]= vio->event_conn_closed; + while (remain != 0) { - if (WaitForSingleObject(vio->event_server_read, - vio->net->write_timeout*1000) != - WAIT_OBJECT_0) + if (WaitForMultipleObjects(array_elements(events), events, FALSE, + vio->net->write_timeout*1000) != WAIT_OBJECT_0) { DBUG_RETURN((size_t) -1); } |