My class for handling processes, somewhat shortened for simplicity, looks like this:
class LocalEngine:
def __init__(self):
name_to_pid = {}
def run_instance(self, name):
args = ... # Computing args for Popen from arguments
with open(f"out-{name}", 'a') as out, open(f"err-{name}", 'a') as err:
pid = \
subprocess.Popen(args, stdout=out, stderr=err, shell=False).pid
print(f"Created process {pid}")
self.name_to_pid[name] = pid
def kill_instance(self, name):
pid = self.name_to_pid[name]
print(f"Killing process {pid}")
psutil.Process(pid).kill()
There is only one object engine
of type LocalEngine
and all processes are created using engine.run_instance
. At the end, all processes are killed using engine.kill_instance
.
Here is the relevant part of the main script's output (under Ubuntu):
Created process 9676
Created process 9703
Killing process 9703
Killing process 9676
However, this is what ps auxfww
outputs after all processes are created:
root 27576 0.0 0.0 896 80 ? S 10:33 0:00 \_ /init
meir 27577 0.0 0.0 10688 5944 pts/2 Ss 10:33 0:00 \_ -bash
meir 9667 2.2 0.0 24296 16956 pts/2 S+ 15:26 0:00 \_ python -m examples.agent_assignment.run_server
meir 9668 0.3 0.0 392712 16732 pts/2 Sl+ 15:26 0:00 \_ python -m examples.agent_assignment.run_server
meir 9676 1.9 0.0 24016 16340 pts/2 S+ 15:26 0:00 \_ python -m src.run_backup 127.0.1.1 57785 server-1
meir 9677 3.7 0.0 392784 14648 pts/2 Sl+ 15:26 0:00 | \_ python -m src.run_backup 127.0.1.1 57785 server-1
meir 9703 8.0 0.0 28364 21084 pts/2 S+ 15:26 0:00 \_ python -m examples.agent_assignment.run_client 127.0.1.1 57785 client-1 2
meir 9704 10.0 0.0 765568 18912 pts/2 Sl+ 15:26 0:00 \_ python -m examples.agent_assignment.run_client 127.0.1.1 57785 client-1 2
run_server
is the main script. The two calls to Popen
run the scripts named run_backup
and run_client
, respectively. The above output of ps
shows that, for some reason, there are two processes for each call of Popen
. Since I pass shell=False
to Popen
, I would not expect that to happen. Here is the output of ps
after the processes are killed:
root 27575 0.0 0.0 896 80 ? Ss 10:33 0:00 /init
root 27576 0.0 0.0 896 80 ? S 10:33 0:00 \_ /init
meir 27577 0.0 0.0 10688 5944 pts/2 Ss+ 10:33 0:00 \_ -bash
meir 9677 0.1 0.0 466516 14736 pts/2 Sl 15:26 0:00 \_ python -m src.run_backup 127.0.1.1 57785 server-1
meir 9704 0.0 0.0 749176 21088 pts/2 Sl 15:26 0:00 \_ python -m examples.agent_assignment.run_client 127.0.1.1 57785 client-1 2
What are these extra processes that linger? How do I prevent them from being created?
EDIT AFTER FEEDBACK:
Based on the reply by @AKX I changed the kill_instance
method. I cannot switch to storing process objects instead of pid's due to the requirement of unpickling by another process.
def kill_instance(self, name):
# Process tree with full commands: ps auxfww
pid = self.name_to_pid[name]
print(f"Terminating process {pid}")
proc = psutil.Process(pid)
proc.terminate()
print(f"Waiting for process {proc} to terminate")
try:
proc.wait(timeout=10)
except subprocess.TimeoutExpired:
print(f"Process {pid} did not terminate in time, killing it")
proc.kill()
The exception is not triggered, but there are still processes lingering as in the original question...
UPDATE:
Got it! The second process appears because of starting multiprocessing
manager. Now the question is how to terminate both the process and the manager...