Different child termination behavior during Kernel shutdown on Posix and Windows systems
- 主要言語
- Python
- スター
- 734
- フォーク
- 412
- 平均マージ
- 1日 5時間
- マージ済み PR(30日)
- 8
説明
Hello,
I've developed a custom Kernel inheriting from the IPython Kernel. This Kernel initiates a child process, and I aim to manage this process' lifecycle independently of the Kernel's shutdown workflow. To achieve this independence, I start the child process as a new process group. This approach functions as expected in POSIX systems, as the IPython Kernel verifies if the kernel process group is distinct from the child process group. However, a divergence in behavior arises when attempting the same workflow on Windows. This discrepancy stems from the IPython Kernel's behavior of returning all children of the Kernel process and subsequently sending SIGTERM signals to them. Please refer:
https://github.com/ipython/ipykernel/blob/main/ipykernel/kernelbase.py#L1218:L1227 and https://github.com/ipython/ipykernel/blob/main/ipykernel/kernelbase.py#L1216:L1217
I understand that it is not straightforward to determine the process group equivalence in Windows OS without using lower-level win32 APIs but this difference in behavior is causing issues in my custom kernel workflows.
Can I achieve my requirements without having to make any changes to the IPython Kernel? My proposed solution involves introducing an instance-level variable in the base Kernel class, which, if set to `False`, ensures that the Kernel refrains from terminating child processes by default during Kernel shutdown.
Here's a potential implementation:
self.terminate_all_children: bool = True # Set to true by default to maintain backward-compatibility
This variable is then checked in the _process_children() method to determine whether to process the children or not.
kernel_process = psutil.Process()
all_children = kernel_process.children(recursive=True)
process_group_children = []
if not self.terminate_all_children:
return process_group_children
else:
if os.name == "nt":
return all_children
kernel_pgid = os.getpgrp()
for child in all_children:
try:
child_pgid = os.getpgid(child.pid)
except OSError:
pass
else:
if child_pgid == kernel_pgid:
process_group_children.append(child)
return process_group_children
By setting `terminate_all_children` to `False` in the subclass, I ensure that the IPython Kernel doesn't terminate the child process by default when Kernel shutdown is initiated.
I'd appreciate your thoughts on this proposed solution. If it aligns with your expectations, I'm prepared to submit a PR. Thank you in advance!
コントリビューションガイド
評価
この issue はまだ評価されていません。