diff --git a/src/common/pl/plpgsql/src/pl_debugger.cpp b/src/common/pl/plpgsql/src/pl_debugger.cpp index 22f342625a309b5e6823eb65a2bc2773045f78ea..f75f68ce7778acd5420b39c878fe8db0bb4228b4 100644 --- a/src/common/pl/plpgsql/src/pl_debugger.cpp +++ b/src/common/pl/plpgsql/src/pl_debugger.cpp @@ -1452,6 +1452,7 @@ void WaitSendMsg(int commIdx, bool isClient, char** destBuffer, int* destLen) { int rc = 0; PlDebuggerComm* debug_comm = &g_instance.pldebug_cxt.debug_comm[commIdx]; + bool mutexLocked = true; pthread_mutex_lock(&debug_comm->mutex); PG_TRY(); { @@ -1461,7 +1462,21 @@ void WaitSendMsg(int commIdx, bool isClient, char** destBuffer, int* destLen) /* server wait for client msg */ debug_comm->IsServerWaited = true; while (debug_comm->hasClientFlushed == false) { - CHECK_FOR_INTERRUPTS(); + /* + * The PlDebugger Server has acquired the lock while waiting. + * When it receives the database stop signal, it exits the thread in the processing interrupt. + * This will call PlDebuggerCleanUp() to clean up, and it will acquire mutex again, + * which will lead to dead waiting. + * So when need to handle interrupt, need to release the lock before calling CHECK_FOR_INTERRUPTS(). + */ + if (InterruptPending) { + pthread_mutex_unlock(&debug_comm->mutex); + mutexLocked = false; + CHECK_FOR_INTERRUPTS(); + pthread_mutex_lock(&debug_comm->mutex); + mutexLocked = true; + continue; + } if (cur_time >= u_sess->attr.attr_sql.pldebugger_timeout) { ereport(ERROR, (errmodule(MOD_PLDEBUGGER), errcode(ERRCODE_PLDEBUGGER_TIMEOUT), @@ -1494,7 +1509,14 @@ void WaitSendMsg(int commIdx, bool isClient, char** destBuffer, int* destLen) /* client wait for server msg */ debug_comm->IsClientWaited = true; while (debug_comm->hasServerFlushed == false) { - CHECK_FOR_INTERRUPTS(); + if (InterruptPending) { + pthread_mutex_unlock(&debug_comm->mutex); + mutexLocked = false; + CHECK_FOR_INTERRUPTS(); + pthread_mutex_lock(&debug_comm->mutex); + mutexLocked = true; + continue; + } if (cur_time >= u_sess->attr.attr_sql.pldebugger_timeout) { ereport(ERROR, (errmodule(MOD_PLDEBUGGER), errcode(ERRCODE_PLDEBUGGER_TIMEOUT), @@ -1535,7 +1557,8 @@ void WaitSendMsg(int commIdx, bool isClient, char** destBuffer, int* destLen) debug_comm->IsClientWaited = false; debug_comm->hasServerFlushed = false; } - pthread_mutex_unlock(&debug_comm->mutex); + if (mutexLocked) + pthread_mutex_unlock(&debug_comm->mutex); PG_RE_THROW(); } diff --git a/src/test/regress/input/pldebugger_shutdown.source b/src/test/regress/input/pldebugger_shutdown.source new file mode 100644 index 0000000000000000000000000000000000000000..99e7b1ab76c8056263246703498d7afea00f9ed9 --- /dev/null +++ b/src/test/regress/input/pldebugger_shutdown.source @@ -0,0 +1,74 @@ +------------------------------------- +-- 测试pldebugger在调试过程中不会阻塞停库 +------------------------------------- + +-- initdb +\! mkdir -p @abs_srcdir@/tmp_check/pldebugger_shutdown +\! rm -rf @abs_srcdir@/tmp_check/pldebugger_shutdown/* +-- */ +\! @abs_bindir@/gs_initdb -w test@123 -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode --nodename='datanode_pldebugger_shutdow' > @abs_srcdir@/tmp_check/pldebugger_shutdown/initdb.log 2>&1 + +-- 设置参数 +\! port=`expr @portstring@ + 5` && (netstat -nlt | grep $port) +\! port=`expr @portstring@ + 5 + 1` && (netstat -nlt | grep $port) +\! port=`expr @portstring@ + 5` && @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "port=$port" 2>&1 | grep Success +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "log_directory='@abs_srcdir@/tmp_check/pldebugger_shutdown/log'" 2>&1 | grep Success +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "enable_thread_pool=off" 2>&1 | grep Success + +-- start +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/start.log 2>&1 +\! sleep 5 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "show log_directory; show enable_thread_pool;" + +-- create function +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "create or replace function func_test_pldbg_shutdown(inout id numeric(6,1)) as \$\$ begin id := id + 10; return; end \$\$ language plpgsql;" + + +-- 通过 pg_cancel_backend() 取消调试函数 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select pg_sleep(1); select pg_cancel_backend(pid) from pg_stat_activity where query = 'select func_test_pldbg_shutdown(1);' and state = 'active';" + +\! sleep 3 +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + +-- 通过 pg_terminate_backend() 取消调试函数 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select pg_sleep(2); select pg_terminate_backend(pid) from pg_stat_activity where query = 'select func_test_pldbg_shutdown(1);' and state = 'active';" + +\! sleep 3 +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + +-- 测试调试函数过程中,停止数据库 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! sleep 3 + +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/stop.log 2>&1 +\! sleep 5 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running + +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + + +------- +-- enable_thread_pool=on +------- +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "enable_thread_pool=on" 2>&1 | grep Success +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/start2.log 2>&1 +\! sleep 5 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "show enable_thread_pool;" + +-- 测试调试函数过程中,停止数据库 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! sleep 3 + +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/stop2.log 2>&1 +\! sleep 5 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running + +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + + +-- 清理 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode || rm -rf @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode diff --git a/src/test/regress/output/pldebugger_shutdown.source b/src/test/regress/output/pldebugger_shutdown.source new file mode 100644 index 0000000000000000000000000000000000000000..e36761a2bd3b5d0abcaa39e3e3bb2516cf058c3d --- /dev/null +++ b/src/test/regress/output/pldebugger_shutdown.source @@ -0,0 +1,158 @@ +------------------------------------- +-- 测试pldebugger在调试过程中不会阻塞停库 +------------------------------------- +-- initdb +\! mkdir -p @abs_srcdir@/tmp_check/pldebugger_shutdown +\! rm -rf @abs_srcdir@/tmp_check/pldebugger_shutdown/* +-- */ +\! @abs_bindir@/gs_initdb -w test@123 -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode --nodename='datanode_pldebugger_shutdow' > @abs_srcdir@/tmp_check/pldebugger_shutdown/initdb.log 2>&1 +-- 设置参数 +\! port=`expr @portstring@ + 5` && (netstat -nlt | grep $port) +\! port=`expr @portstring@ + 5 + 1` && (netstat -nlt | grep $port) +\! port=`expr @portstring@ + 5` && @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "port=$port" 2>&1 | grep Success +Success to perform gs_guc! +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "log_directory='@abs_srcdir@/tmp_check/pldebugger_shutdown/log'" 2>&1 | grep Success +Success to perform gs_guc! +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "enable_thread_pool=off" 2>&1 | grep Success +Success to perform gs_guc! +-- start +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/start.log 2>&1 +\! sleep 5 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "show log_directory; show enable_thread_pool;" +--?.* +--?.* + @abs_srcdir@/tmp_check/pldebugger_shutdown/log +(1 row) + + enable_thread_pool +-------------------- + off +(1 row) + +-- create function +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "create or replace function func_test_pldbg_shutdown(inout id numeric(6,1)) as \$\$ begin id := id + 10; return; end \$\$ language plpgsql;" +-- 通过 pg_cancel_backend() 取消调试函数 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select pg_sleep(1); select pg_cancel_backend(pid) from pg_stat_activity where query = 'select func_test_pldbg_shutdown(1);' and state = 'active';" + pg_sleep +---------- + +(1 row) + + pg_cancel_backend +------------------- + t +(1 row) + +\! sleep 3 +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + func_test_pldbg_shutdown +-------------------------- + 11 +(1 row) + + turn_on +--------------------------------- + (datanode_pldebugger_shutdow,0) +(1 row) + +ERROR: canceling statement due to user request +CONTEXT: PL/pgSQL function func_test_pldbg_shutdown(numeric) line 1 at assignment +referenced column: func_test_pldbg_shutdown +-- 通过 pg_terminate_backend() 取消调试函数 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select pg_sleep(2); select pg_terminate_backend(pid) from pg_stat_activity where query = 'select func_test_pldbg_shutdown(1);' and state = 'active';" + pg_sleep +---------- + +(1 row) + + pg_terminate_backend +---------------------- + t +(1 row) + +\! sleep 3 +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + func_test_pldbg_shutdown +-------------------------- + 11 +(1 row) + + turn_on +--------------------------------- + (datanode_pldebugger_shutdow,0) +(1 row) + +FATAL: terminating connection due to administrator command +CONTEXT: PL/pgSQL function func_test_pldbg_shutdown(numeric) line 1 at assignment +referenced column: func_test_pldbg_shutdown +FATAL: terminating connection due to administrator command +CONTEXT: PL/pgSQL function func_test_pldbg_shutdown(numeric) line 1 at assignment +referenced column: func_test_pldbg_shutdown +connection to server was lost +-- 测试调试函数过程中,停止数据库 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! sleep 3 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running +--?gs_ctl: server is running .* +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/stop.log 2>&1 +\! sleep 5 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running +no server running +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + func_test_pldbg_shutdown +-------------------------- + 11 +(1 row) + + turn_on +--------------------------------- + (datanode_pldebugger_shutdow,0) +(1 row) + +FATAL: terminating connection due to administrator command +CONTEXT: PL/pgSQL function func_test_pldbg_shutdown(numeric) line 1 at assignment +referenced column: func_test_pldbg_shutdown +FATAL: terminating connection due to administrator command +CONTEXT: PL/pgSQL function func_test_pldbg_shutdown(numeric) line 1 at assignment +referenced column: func_test_pldbg_shutdown +connection to server was lost +------- +-- enable_thread_pool=on +------- +\! @abs_bindir@/gs_guc set -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode -c "enable_thread_pool=on" 2>&1 | grep Success +Success to perform gs_guc! +\! @abs_bindir@/gs_ctl start -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/start2.log 2>&1 +\! sleep 5 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "show enable_thread_pool;" + enable_thread_pool +-------------------- + on +(1 row) + +-- 测试调试函数过程中,停止数据库 +\! port=`expr @portstring@ + 5` && @abs_bindir@/gsql -X -q -d postgres -p $port -c "select func_test_pldbg_shutdown(1); select dbe_pldebugger.turn_on(oid) from pg_proc where proname = 'func_test_pldbg_shutdown'; select func_test_pldbg_shutdown(1);" > @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log 2>&1 & +\! sleep 3 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running +--?gs_ctl: server is running .* +\! @abs_bindir@/gs_ctl stop -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode > @abs_srcdir@/tmp_check/pldebugger_shutdown/stop2.log 2>&1 +\! sleep 5 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode | grep running +no server running +\! cat @abs_srcdir@/tmp_check/pldebugger_shutdown/temp.log + func_test_pldbg_shutdown +-------------------------- + 11 +(1 row) + + turn_on +--------------------------------- + (datanode_pldebugger_shutdow,0) +(1 row) + +connection to server was lost +-- 清理 +\! @abs_bindir@/gs_ctl status -D @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode || rm -rf @abs_srcdir@/tmp_check/pldebugger_shutdown/datanode +--?.* +no server running diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index 97085128df133f58894b7450c94245d48a76665c..aa14fd8f0eb20774038916038dc31cf84d6c5011 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -1008,7 +1008,7 @@ test: test_astore_multixact test: row_compression/pg_table_size row_compression/unsupported_feature row_compression/normal_test # test: row_compression/pg_tablespace_size test: row_compression/twophase -test: row_compression/row_compress_feature +test: row_compression/row_compress_feature pldebugger_shutdown test: row_compression/row_compression_basebackup test: component_view_enhancements single_node_user_mapping # reindex concurrently