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

62 views Asked by At

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?

2

There are 2 answers

0
Charles Duffy On BEST ANSWER

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. :)

0
jsbueno On

The one and obvious answer is: just run subprocess.popen likewise to run sudo kill ..., just as you did with to start the process in the first place. A system call made directly by your process won't ever have privileges to kill the higer privileged subprocess.