'python how to cleanup a subprocess

I'm running a python script that will restart a subprocess every 2 hours. code as follow.

import datetime
import os
import signal
import subprocess
import sys
import time


if __name__ == '__main__':
    while True:
        with subprocess.Popen([sys.executable, '/script.py']) as p:
            start_time = datetime.datetime.now()
            try:
                print(f'starting the process at {p.pid}')
                p.communicate(timeout=4800)
            except subprocess.TimeoutExpired:
                print('timeout terminate process')
                os.kill(p.pid, signal.SIGINT)
                p.terminate()
                p.wait(60)
                p.kill()

            dif = datetime.datetime.now()-start_time
            t = 4810-dif.total_seconds()
            print(f'restarting after {t/60} mins')
            time.sleep(t)

in my script.py, I'm having a thread executor that each thread runs a chrome webdriver instance. The issue I'm having is when the process timeout, the python process is terminated but all the webdriver instances are still lingering. Is there a way for the parent process to kill all the spawned child processes aka the chrome driver instances in my case? Running on my mac

Edit: script.py

def run_with_config(user):
  i = WebDriverInstance()
    try:
        return i.run_loop() # while true infinite loop running some ui actions
    except Exception:
        return False
    finally:
        i.quit()

def run(users):
    with concurrent.futures.ThreadPoolExecutor(max_workers=len(user_configs)) as executor:
        f_to_user = {}
        for c in user_configs:
            f = executor.submit(run_with_config, c)
            f_to_user[f] = c
        for f in concurrent.futures.as_completed(f_to_user):
            res = f.result()
            print(res)
  


Solution 1:[1]

passing preexec_fn=os.setpgrp to subprocess popen works for me.

Solution 2:[2]

Run the subprocess in a new process group, then kill the entire group with os.killpg().

if __name__ == '__main__':
    while True:
        with subprocess.Popen([sys.executable, '/script.py'], creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) as p:
            start_time = datetime.datetime.now()
            try:
                print(f'starting the process at {p.pid}')
                p.communicate(timeout=4800)
            except subprocess.TimeoutExpired:
                print('timeout terminate process')
                os.killpg(p.pid, signal.SIGINT)
                p.terminate()
                p.wait(60)
                p.kill()

            dif = datetime.datetime.now()-start_time
            t = 4810-dif.total_seconds()
            print(f'restarting after {t/60} mins')
            time.sleep(t)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Khalil
Solution 2 Barmar