[Bug] PL/Python statement_timeout can leave a zombie subprocess despite finally: wait()
維護者通常 2 天內回覆
評估
這個 Issue 還沒有評估資料。
描述
Apache Cloudberry version
main, probably REL_2_STABLE
What happened
When statement_timeout cancels a PL/Python function waiting in subprocess.Popen.communicate(), the SQL statement can return a cancellation error while its timeout child remains a zombie, despite an explicit process.wait() in a finally block.
The zombie remains a child of the backend after subsequent SQL statements and disappears when the backend session closes. The monitored command itself has already finished.
This was discovered while reviewing #2117, but also reproduces with a harmless sleep command and does not require diskquota or segment recovery.
What you think should happen instead
The exited subprocess should be reaped before the cancellation error is returned to the client.
How to reproduce
The measured runs used coordinator connections with options='-c gp_role=utility' and autocommit enabled.
To reproduce under the same conditions, start an interactive psql session connected to the coordinator. Replace the placeholders with your connection details:
PGOPTIONS='-c gp_role=utility' psql -h <coordinator_host> -p <coordinator_port> -d <database>
Run the following statements with autocommit enabled and without an explicit transaction. Record the value returned by SELECT pg_backend_pid();.
CREATE EXTENSION IF NOT EXISTS plpython3u;
CREATE OR REPLACE FUNCTION public.zombie_repro()
RETURNS void LANGUAGE plpython3u AS $$
import subprocess
p = subprocess.Popen(
['timeout', '-k', '1', '5', 'sleep', '0.3'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
try:
p.communicate()
finally:
p.wait()
$$;
SELECT pg_backend_pid();
SET statement_timeout = '100ms';
SELECT public.zombie_repro();
RESET statement_timeout;
SELECT 1;
Keep the psql session open after the timeout error. From another terminal on the coordinator host, inspect the backend’s child processes, replacing <backend_pid> with the recorded PID:
ps -o pid,ppid,stat,comm --ppid <backend_pid>
When the issue reproduces, a timeout process appears with STAT containing Z and PPID matching the backend PID. It persists after subsequent SQL statements and disappears when the session closes.
The result is timing-dependent and does not occur on every invocation. If necessary, repeat the procedure using a fresh connection for each attempt.
Observed reproduction rates:
- Minimal example above: 16 out of 20 independent backend sessions.
- Exact
pg_recoverseghelper from #2117, invoking realgprecoverseg: 12 out of 20 independent backend sessions.
Every attempt returned SQLSTATE 57014 from the function call. Zombie detection was performed after RESET statement_timeout, a 200 ms delay, and SELECT 1. A separate check confirmed persistence after two seconds and another SELECT 1.
Each attempt closed its connection afterwards, so the counts do not include children left by previous attempts.
Operating System
Any
Anything else
The results above were verified in this environment:
- Ubuntu 22.04, Linux x86_64.
- Python 3.10.12.
- Cloudberry 3.0.0-devel / PostgreSQL 16.9, with assertions enabled.
- Server source commit:
070d9d33b3bacea45d991f54c100b4bc077c8d58.
Possible cause to investigate: StatementTimeoutHandler signals both the backend process group and the backend PID, while PLy_handle_cancel_interrupt queues KeyboardInterrupt through Py_AddPendingCall. Repeated cancellation may interrupt cleanup. This is a hypothesis, not a confirmed root cause.
Are you willing to submit PR?
- Yes, I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct.
- 主要語言
- C
- 星號
- 1.4k
- 分支
- 265
- 平均合併
- 3 天 17 小時
- 30 天內合併 PR
- 68
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
apache/cloudberry 的其他 Issue
-
[Bug] Expand fails to recognize user-defined tablespaces可能已有人在做 @nix-oss 於 73 天前認領。 未關閉type: Bug
難度 2/5 1-3 小時 新手友好度 76/100
apache/cloudberry#1885 · 2 個 reaction ·
維護者通常 2 天內回覆
-
gpexpand first stage fails: 'SyncPackages' object has no attribute 'ret' (extension sync never runs; regression)可能已有人在做 @talmacschen-arch 於 134 天前認領。 未關閉
難度 2/5 1-3 小時 新手友好度 86/100
apache/cloudberry#1825 ·
維護者通常 2 天內回覆
-
[Bug] GPORCA: “could not find MotionState” for correlated EXISTS with LIMIT and a scalar subquery可能已有人在做 @Alena0704 於 1 天前認領。 未關閉type: Bug
apache/cloudberry#2221 · 已指派 1 人 ·
維護者通常 2 天內回覆
-
難度 4/5 3-5 天 新手友好度 42/100
apache/cloudberry#2214 · 1 則留言 ·
維護者通常 2 天內回覆
-
難度 4/5 3-5 天 新手友好度 35/100
apache/cloudberry#2213 · 4 則留言 ·
維護者通常 2 天內回覆
查看 apache/cloudberry 的全部 Issue
相似的 Issue
-
難度 2/5 1-3 小時 新手友好度 72/100
ly05010419/MacNativeGames#1420 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 62/100
JustAResearcher/gpu-unlock-ada#124 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 74/100
swoole/swoole-cli#1092 ·
-
難度 2/5 1-3 小時 新手友好度 62/100
-
inflate: total_in uses plain += on c_ulong (32-bit on Windows), panics in debug for streams > 4 GiB未關閉
難度 1/5 1 小時以內 新手友好度 85/100
trifectatechfoundation/zlib-rs#570 · 1 則留言 ·