pythonunixsubprocesspopenkill

Cannot kill Popen process


I have a Python program with the following structure and necessary imports:

def startLogger(logger_dir):
    command0 = 'adb logcat -c'
    command1 = 'adb logcat'
    command2 = 'python3 '+logger_dir+'main.py'

    clear_logcat = subprocess.run(command0.split())
    logcatHandle = subprocess.Popen(command1.split(),stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
    loggerHandle = subprocess.Popen(command2.split(),stdin=logcatHandle.stdout,shell=False)
    return logcatHandle, loggerHandle

def closeLogger(logcatInstance, loggerInstance):
    loggerInstance.kill() #Killing it first so that it doesn't break the input PIPE
    logcatInstance.kill()
    return logcatInstance, loggerInstance

def main():
    logger_dir = '/Users/Desktop/logger/'
    print("Starting Logger")
    logcatHandle, loggerHandle = startLogger(logger_dir)
    time.sleep(10)
    logcat, logger = closeLogger(logcatHandle, loggerHandle)

main()

The code works fine, I can execute logcat on my Android device, pull in logs, and feed it to my logger giving me the desired output in a text file created by the logger file. But, I cannot kill both processes. I have tried the terminate() method, os.kill(process.pid, signam.SIGKILL), preexec_fn flag, os.killpg(), etc methods, but still, the logger keeps on running in the background. What can be the possible issue here?


Solution

  • You should ensure that you're properly closing pipe before killing the processes.

    Also, instead of using "kill", use "terminate" to give the process a chance to clean up. If it doesn't, then use "kill".

    Then, make sure that the subprocesses don't inherit unnecessary file descriptors which might keep them running.

    Considering those changes, try with

    import subprocess
    import time
    import os
    import signal
    
    def startLogger(logger_dir):
        command0 = 'adb logcat -c'
        command1 = 'adb logcat'
        command2 = 'python3 ' + logger_dir + 'main.py'
    
        
        clear_logcat = subprocess.run(command0.split())
        logcatHandle = subprocess.Popen(command1.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid)
        loggerHandle = subprocess.Popen(command2.split(), stdin=logcatHandle.stdout, preexec_fn=os.setsid) #this starts each subrprocess in a new session
        return logcatHandle, loggerHandle
    
    def closeLogger(logcatInstance, loggerInstance):
        loggerInstance.terminate()
        try:
            loggerInstance.wait(timeout=5)
        except subprocess.TimeoutExpired:
            loggerInstance.kill()
    
        logcatInstance.terminate()
        try:
            logcatInstance.wait(timeout=5)
        except subprocess.TimeoutExpired:
            logcatInstance.kill()
        
        os.killpg(os.getpgid(logcatInstance.pid), signal.SIGTERM)
        os.killpg(os.getpgid(loggerInstance.pid), signal.SIGTERM)
    #(ensures all processes in the process group are terminated, handling any subprocesses that might have been spawned.)
        
        return logcatInstance, loggerInstance
    
    def main():
        logger_dir = '/Users/Desktop/logger/'
        print("Starting Logger")
        logcatHandle, loggerHandle = startLogger(logger_dir)
        time.sleep(10)
        logcat, logger = closeLogger(logcatHandle, loggerHandle)
        print("Logger stopped")
    
    if __name__ == "__main__":
        main()
    

    Hope it helps.