diff --git a/src/common/backend/catalog/builtin_funcs.ini b/src/common/backend/catalog/builtin_funcs.ini index 4073bb3af..3c0e492ba 100644 --- a/src/common/backend/catalog/builtin_funcs.ini +++ b/src/common/backend/catalog/builtin_funcs.ini @@ -7272,6 +7272,10 @@ "pg_terminate_backend", 1, AddBuiltinFunc(_0(2096), _1("pg_terminate_backend"), _2(1), _3(true), _4(false), _5(pg_terminate_backend), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14('f'), _15(false), _16(false), _17('v'), _18(0), _19(1, 20), _20(NULL), _21(NULL), _22(NULL), _23(NULL), _24("pg_terminate_backend"), _25(NULL), _26(NULL), _27(NULL), _28(0), _29(false), _30(NULL), _31(false)) ), + AddFuncGroup( + "pg_terminate_session", 1, + AddBuiltinFunc(_0(2099), _1("pg_terminate_session"), _2(2), _3(true), _4(false), _5(pg_terminate_session), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14('f'), _15(false), _16(false), _17('v'), _18(0), _19(2, 20, 20), _20(NULL), _21(NULL), _22(NULL), _23(NULL), _24("pg_terminate_session"), _25(NULL), _26(NULL), _27(NULL), _28(0), _29(false), _30(NULL), _31(false)) + ), AddFuncGroup( "pg_test_err_contain_err", 1, AddBuiltinFunc(_0(9999), _1("pg_test_err_contain_err"), _2(1), _3(true), _4(false), _5(pg_test_err_contain_err), _6(2278), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14('f'), _15(false), _16(false), _17('v'), _18(0), _19(1, 23), _20(NULL), _21(NULL), _22(NULL), _23(NULL), _24("pg_test_err_contain_err"), _25(NULL), _26(NULL), _27(NULL), _28(0), _29(false), _30(NULL), _31(false)) diff --git a/src/common/backend/utils/adt/misc.cpp b/src/common/backend/utils/adt/misc.cpp index 97d18641a..f6d559c76 100755 --- a/src/common/backend/utils/adt/misc.cpp +++ b/src/common/backend/utils/adt/misc.cpp @@ -238,15 +238,9 @@ Datum signal_backend(PG_FUNCTION_ARGS) PG_RETURN_BOOL(true); } -/* - * Signal to terminate a backend process. This is allowed if you are superuser - * or have the same role as the process being terminated. - */ -Datum pg_terminate_backend(PG_FUNCTION_ARGS) -{ - ThreadId tid = PG_GETARG_INT64(0); - int r = 0; +static int kill_backend(ThreadId tid) +{ /* * It is forbidden to kill backend in the online expansion to protect * the lock session from being interrupted by external applications. @@ -256,20 +250,49 @@ Datum pg_terminate_backend(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("kill backend is prohibited during online expansion.")))); } - r = pg_signal_backend(tid, SIGTERM); + int r = pg_signal_backend(tid, SIGTERM); if (r == SIGNAL_BACKEND_NOPERMISSION) { ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be system admin or have the same role to terminate other backend")))); } - - if (t_thrd.proc && t_thrd.proc->workingVersionNum >= 92060) { + + if (t_thrd.proc != NULL) { uint64 query_id = get_query_id_beentry(tid); (void)gs_close_all_stream_by_debug_id(query_id); } + + return r; +} + +/* + * Signal to terminate a backend process. This is allowed if you are superuser + * or have the same role as the process being terminated. + */ +Datum pg_terminate_backend(PG_FUNCTION_ARGS) +{ + ThreadId tid = PG_GETARG_INT64(0); + int r = kill_backend(tid); PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS); } +Datum pg_terminate_session(PG_FUNCTION_ARGS) +{ + ThreadId tid = PG_GETARG_INT64(0); + uint64 sid = PG_GETARG_INT64(1); + int r = 0; + + if (tid == sid) { + r = kill_backend(tid); + } else { + ThreadPoolSessControl *sess_ctrl = g_threadPoolControler->GetSessionCtrl(); + int ctrl_idx = sess_ctrl->FindCtrlIdxBySessId(sid); + r = sess_ctrl->SendSignal((int)ctrl_idx, SIGTERM); + } + + PG_RETURN_BOOL(r == 0); +} + /* * function name: pg_wlm_jump_queue * description : wlm jump the queue with thread id. diff --git a/src/gausskernel/cbb/utils/gssignal/gs_signal.cpp b/src/gausskernel/cbb/utils/gssignal/gs_signal.cpp index d7b1a48ea..1d6b4edc4 100644 --- a/src/gausskernel/cbb/utils/gssignal/gs_signal.cpp +++ b/src/gausskernel/cbb/utils/gssignal/gs_signal.cpp @@ -215,6 +215,10 @@ static void gs_signal_send_mark(GsNode* local_node, GsSignalCheckType check_type } break; } + case SIGNAL_CHECK_SESS_KEY: { + local_node->sig_data.check.session_id = t_thrd.sig_cxt.session_id; + break; + } default: { break; } @@ -670,6 +674,14 @@ static bool gs_signal_handle_check(const GsSndSignal* local_node) } break; } + case SIGNAL_CHECK_SESS_KEY: { + if (u_sess != NULL && local_node->check.session_id == u_sess->session_id) { + return true; + } else { + return false; + } + break; + } default: { break; } diff --git a/src/gausskernel/process/threadpool/threadpool_sessctl.cpp b/src/gausskernel/process/threadpool/threadpool_sessctl.cpp index 09d4154f7..115ae2c94 100644 --- a/src/gausskernel/process/threadpool/threadpool_sessctl.cpp +++ b/src/gausskernel/process/threadpool/threadpool_sessctl.cpp @@ -216,6 +216,17 @@ int ThreadPoolSessControl::SendSignal(int ctrl_index, int signal) } knl_sess_control* ctrl = &m_base[ctrl_index - m_maxReserveSessionCount]; + knl_session_context* sess = ctrl->sess; + + /* check permission */ + if (!superuser()) { + if (sess->proc_cxt.MyRoleId != GetUserId()) { + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("must be system admin or have the same role to terminate other backend")))); + } + } + volatile sig_atomic_t* plock = &ctrl->lock; sig_atomic_t val; do { @@ -223,13 +234,18 @@ int ThreadPoolSessControl::SendSignal(int ctrl_index, int signal) /* perform an atomic compare and swap. */ val = __sync_val_compare_and_swap(plock, 0, 1); if (val == 0) { - if (ctrl->sess != NULL) { - if (ctrl->sess->status == KNL_SESS_ATTACH) { - status = gs_signal_send(ctrl->sess->attachPid, signal); - } else if (ctrl->sess->status == KNL_SESS_DETACH) { + if (sess != NULL) { + if (sess->status == KNL_SESS_ATTACH) { + t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_SESS_KEY; + t_thrd.sig_cxt.session_id = sess->session_id; + status = gs_signal_send(sess->attachPid, signal); + t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_NONE; + t_thrd.sig_cxt.session_id = 0; + } else if (sess->status == KNL_SESS_DETACH) { switch (signal) { case SIGTERM: - ctrl->sess->status = KNL_SESS_CLOSE; + sess->status = KNL_SESS_CLOSE; + CloseClientSocket(sess, false); status = 0; break; default: @@ -504,3 +520,15 @@ knl_session_context* ThreadPoolSessControl::GetSessionByIdx(int idx) return NULL; } } + +int ThreadPoolSessControl::FindCtrlIdxBySessId(uint64 id) +{ + int cidx = 0; + for (cidx = 0; cidx < m_maxActiveSessionCount; cidx++) { + if (m_base[cidx].sess != NULL && m_base[cidx].sess->session_id == id) { + break; + } + } + + return cidx + m_maxReserveSessionCount; +} diff --git a/src/gausskernel/runtime/executor/opfusion_scan.cpp b/src/gausskernel/runtime/executor/opfusion_scan.cpp index 12f19808b..1fc8cc03e 100644 --- a/src/gausskernel/runtime/executor/opfusion_scan.cpp +++ b/src/gausskernel/runtime/executor/opfusion_scan.cpp @@ -485,7 +485,7 @@ IndexOnlyScanFusion::IndexOnlyScanFusion(IndexOnlyScan* node, PlannedStmt* plans m_keyInit = false; m_keyNum = list_length(node->indexqual); - ; + m_scanKeys = (ScanKey)palloc0(m_keyNum * sizeof(ScanKeyData)); /* init params */ diff --git a/src/include/gssignal/gs_signal.h b/src/include/gssignal/gs_signal.h index 58306cf77..c3cd9777f 100755 --- a/src/include/gssignal/gs_signal.h +++ b/src/include/gssignal/gs_signal.h @@ -38,13 +38,15 @@ typedef void (*gs_sigfunc)(int); typedef enum GsSignalCheckType { SIGNAL_CHECK_NONE, SIGNAL_CHECK_EXECUTOR_STOP, - SIGNAL_CHECK_STREAM_STOP + SIGNAL_CHECK_STREAM_STOP, + SIGNAL_CHECK_SESS_KEY } GsSignalCheckType; /* the struct of signal check */ typedef struct GsSignalCheck { GsSignalCheckType check_type; uint64 debug_query_id; + uint64 session_id; } GsSignalCheck; /* the struct of signal to be handled and the signal sender's thread id */ diff --git a/src/include/knl/knl_thread.h b/src/include/knl/knl_thread.h index 4a2939477..9dd03559b 100644 --- a/src/include/knl/knl_thread.h +++ b/src/include/knl/knl_thread.h @@ -1929,6 +1929,7 @@ typedef struct knl_t_libwalreceiver_context { typedef struct knl_t_sig_context { unsigned long signal_handle_cnt; GsSignalCheckType gs_sigale_check_type; + uint64 session_id; } knl_t_sig_context; typedef struct knl_t_slot_context { diff --git a/src/include/threadpool/threadpool_sessctl.h b/src/include/threadpool/threadpool_sessctl.h index 996ead02b..d035e0437 100644 --- a/src/include/threadpool/threadpool_sessctl.h +++ b/src/include/threadpool/threadpool_sessctl.h @@ -76,6 +76,7 @@ public: void HandlePoolerReload(); SessionMemoryDetail* getSessionMemoryDetail(uint32* num); knl_session_context* GetSessionByIdx(int idx); + int FindCtrlIdxBySessId(uint64 id); inline int GetActiveSessionCount() { diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 058b46292..b4e9545c7 100755 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -580,6 +580,7 @@ extern Datum pg_cancel_invalid_query(PG_FUNCTION_ARGS); extern Datum report_fatal(PG_FUNCTION_ARGS); extern Datum signal_backend(PG_FUNCTION_ARGS); extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); +extern Datum pg_terminate_session(PG_FUNCTION_ARGS); extern Datum pg_reload_conf(PG_FUNCTION_ARGS); extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS); extern Datum pg_tablespace_location(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 94ffb71ba..ca1a3f9f4 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -1146,6 +1146,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1; 2096 | pg_terminate_backend 2097 | pg_get_variable_info 2098 | pg_get_functiondef + 2099 | pg_terminate_session 2100 | avg 2101 | avg 2102 | avg @@ -2637,7 +2638,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1; 9016 | pg_advisory_lock 9017 | pgxc_unlock_for_sp_database 9999 | pg_test_err_contain_err -(2275 rows) +(2276 rows) -- **************** pg_cast **************** -- Catch bogus values in pg_cast columns (other than cases detected by diff --git a/src/test/regress/expected/single_node_opr_sanity.out b/src/test/regress/expected/single_node_opr_sanity.out index 4178e37e2..5c059615d 100755 --- a/src/test/regress/expected/single_node_opr_sanity.out +++ b/src/test/regress/expected/single_node_opr_sanity.out @@ -1185,6 +1185,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1; 2096 | pg_terminate_backend 2097 | pg_get_variable_info 2098 | pg_get_functiondef + 2099 | pg_terminate_session 2100 | avg 2101 | avg 2102 | avg @@ -2676,7 +2677,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1; 9016 | pg_advisory_lock 9017 | pgxc_unlock_for_sp_database 9999 | pg_test_err_contain_err -(2275 rows) +(2276 rows) -- Check prokind select count(*) from pg_proc where prokind = 'a'; @@ -2694,7 +2695,7 @@ select count(*) from pg_proc where prokind = 'w'; select count(*) from pg_proc where prokind = 'f'; count ------- - 3149 + 3150 (1 row) select count(*) from pg_proc where prokind = 'p';