From dab56d5e8e9c64d3815594b412521e36ba539f48 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 3 Oct 2020 00:24:53 +0200 Subject: MDEV-23879 server hangs with threadpool, compression, and client pipelining Amend check for unread client data in threadpool. THD::NET will have unread data, in case client uses compression, and wraps multiple commands into a single compression packet MariaDB C/C sends COM_STMT_RESET+COM_STMT_EXECUTE, and wraps it into a single compressed packet, when compression is on, thus trying to use compression and prepared statements against a threadpool-enabled server will result into a hang, before this patch. --- mysql-test/r/pool_of_threads.result | 5 +++++ mysql-test/t/pool_of_threads.test | 6 ++++++ sql/threadpool_common.cc | 14 +++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/pool_of_threads.result b/mysql-test/r/pool_of_threads.result index 9c02dfac9cd..5f501eb1b68 100644 --- a/mysql-test/r/pool_of_threads.result +++ b/mysql-test/r/pool_of_threads.result @@ -2188,3 +2188,8 @@ sleep(50) connection extracon; sleep(5.5) 0 +connect comp_con,localhost,root,,,,,COMPRESS; +SELECT 1; +1 +1 +disconnect comp_con; diff --git a/mysql-test/t/pool_of_threads.test b/mysql-test/t/pool_of_threads.test index cb62a27faeb..95b320e6dad 100644 --- a/mysql-test/t/pool_of_threads.test +++ b/mysql-test/t/pool_of_threads.test @@ -92,3 +92,9 @@ connection con2; connection extracon; --reap + +# Check if compression works OK +connect (comp_con,localhost,root,,,,,COMPRESS); +SELECT 1; +disconnect comp_con; + diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index b0438770aae..fc9a79432f0 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -324,6 +324,16 @@ static void handle_wait_timeout(THD *thd) thd->net.error= 2; } +/** Check if some client data is cached in thd->net or thd->net.vio */ +static bool has_unread_data(THD* thd) +{ + NET *net= &thd->net; + if (net->compress && net->remain_in_buf) + return true; + Vio *vio= net->vio; + return vio->has_data(vio); +} + /** Process a single client request or a single batch. @@ -358,7 +368,6 @@ static int threadpool_process_request(THD *thd) */ for(;;) { - Vio *vio; thd->net.reading_or_writing= 0; if (mysql_audit_release_required(thd)) mysql_audit_release(thd); @@ -374,8 +383,7 @@ static int threadpool_process_request(THD *thd) set_thd_idle(thd); - vio= thd->net.vio; - if (!vio->has_data(vio)) + if (!has_unread_data(thd)) { /* More info on this debug sync is in sql_parse.cc*/ DEBUG_SYNC(thd, "before_do_command_net_read"); -- cgit v1.2.1