Search code examples
pythonsubprocess

How can I kill a process my Python executable started with sudo?


I'm using this Python code to run a C++ executable:

import os
import subprocess
import signal
import time

def trench():
    return subprocess.Popen(
        ['sudo', './Trench.out'],
        stdout=subprocess.DEVNULL,
        stderr=subprocess.STDOUT,
    )

trench_display = trench()

time.sleep(5)

os.kill(trench_display.pid, signal.SIGINT)

I've also tried this, but it didn't seem to make any difference:

trench_display.send_signal(signal.SIGINT)

The issue is that when the Python code ends, the C++ executable continues to run. If I type any command and press enter, the terminal becomes glitchy and the program doesn’t seem to exit gracefully.

However, if I execute it directly from the terminal and use kill -2 PID or Ctrl + C, it exits gracefully. So, I believe the problem lies with Python’s subprocess.

I understand that this is a quirk of Python’s subprocess, but I’m wondering if there’s a way to fix it, without modifying the C++ source code?


Solution

  • While in the real world you were able to resolve this by updating permissions to make sudo no longer necessary to perform i2c operations (which is certainly the best way to address this!), here's an alternate approach that fits within the bounds of the question:

    import os
    import subprocess
    import signal
    import time
    
    def trench():
        p1 = subprocess.Popen(
            ['sudo', './Trench.out'],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.PIPE,
        )
        p2 = subprocess.Popen(['cat'], stdin=p1.stdout)
        p1.stdout.close()
        return p2
    
    trench_display = trench()
    time.sleep(5)
    trench_display.send_signal(signal.SIGTERM)
    

    Note that trench_display no longer refers to sudo ./Trench.out but instead refers to cat, so when you kill it, the next time Trench.out tries to write to its stderr it'll get an EPIPE error and a SIGPIPE signal; unless it's explicitly trying to ignore both these things, this should cause Trench to exit even when it's running as a more-privileged user.

    You could of course write Python code to copy from p1.stdout to the Python project's stdout -- using cat is a cheat to keep this answer short. :)