杀死无限循环plperl

Łuk*_*ski 5 postgresql perl hang kill

如何使用无限循环的 plperl 函数终止会话?

双方pg_terminate_backendpg_cancel_backend没有任何影响。kill -1 pid什么也没做,kill -9 pid服务器崩溃了。

Eva*_*oll 5

你是对的,

CREATE FUNCTION foo()
RETURNS void
AS $$
  while(1) {}
$$ LANGUAGE plperl;

SELECT * FROM foo();
Run Code Online (Sandbox Code Playgroud)

在传唤pg_terminate_backendpg_cancel_backend那plperl后端依然存在。似乎是他们已经知道的错误,从 Tom Lane 说的列表中,

即使假设我们可以修复这些常见的pg_terminate_backend错误,仍然存在一个基本问题,即不合作的用户函数(尤其是 plperl/pltcl/plpython 中的一个)可能无限延迟对. 也许没关系,看到它同样可以推迟或无视QueryCancel,但我不确定要求这个的人真的会满意。(我们应该考虑的一件事是使ERRCODE_ADMIN_SHUTDOWNplpgsql 异常块无条件地不可捕获,这至少可以解决 plpgsql 函数的问题。)

我不确定他们是否有解决方案。来自克雷格·林格,

一般来说,pg_terminate_backend作为“更大的锤子”使用是安全的。SIGTERM正如所发送的那样, pg_terminate_backend()通常(但并非总是)会导致无法响应取消的后端退出。

他甚至解释了一些可能导致挂起的选项。

无论如何,让我们尝试一下

CREATE FUNCTION foo()
RETURNS void
AS $$
  $SIG{INT} = $SIG{TERM} = sub { die; };
  while(1) {}
$$ LANGUAGE plperl;
Run Code Online (Sandbox Code Playgroud)

然后我跑了

SESSION 1                           SESSION 2

SELECT pg_backend_pid();
 pg_backend_pid 
----------------
          20465

SELECT * FROM foo();
-- LOOPING

                                    pg_terminate_backend(20465);


ERROR:  Died at line 2.
CONTEXT:  PL/Perl function "foo"
Run Code Online (Sandbox Code Playgroud)

如果可以的话,这似乎可行。