ipython / ipython/ipykernel

Different child termination behavior during Kernel shutdown on Posix and Windows systems

Aperta
#1,232 1 commento 1 reazione 0 assegnatari Vedi su GitHub
Lingua principale
Python
Stelle
734
Fork
412
Merge medio
1g 5h
PR unite (30g)
8

Descrizione

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!

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.