Rod
Rod

Reputation: 15475

Popen not responding to kill

Environment: Raspberry Pi Wheezy

I have a python program that uses Popen to call another python program

from subprocess import *

oJob = Popen('sudo python mypgm.py',shell=True)

Another menu option is supposed to end the job immediately

oJob.kill()

but the job is still running??

Upvotes: 1

Views: 1266

Answers (2)

t3dodson
t3dodson

Reputation: 4007

You need to add a creation flag arg

oJob = Popen('sudo python mypgm.py',shell=True, creationflags = subprocess.CREATE_NEW_PROCESS_GROUP)

source

subprocess.CREATE_NEW_PROCESS_GROUP A Popen creationflags parameter to specify that a new process group will be created. This flag is necessary for using os.kill() on the subprocess.

EDIT I agree with the comment on how to import stuff and why you are getting something is undefined. Also the other answer seems to be on the right track getting the pid

import subprocess as sub

oJob = sub.Popen('sudo python mypgm.py', creationflags = sub.CREATE_NEW_PROCESS_GROUP)
oJob.kill()

Warning Executing shell commands that incorporate unsanitized input from an untrusted source makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. For this reason, the use of shell=True is strongly discouraged in cases where the command string is constructed from external input:

Upvotes: 1

Saravana Kumar
Saravana Kumar

Reputation: 394

When you add the option shell=True, python launches a shell and the shell in turn launches the process python mymgm.py. You are killing the shell process here which doesn't kill its own child that runs mymgm.py.

To ensure, that child process gets killed on oJob.kill, you need to group them all under one process group and make shell process, the group leader. The code is,

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(pro.pid, signal.SIGTERM)  # Send the signal to all the process groups

When you send SIGTERM signal to the shell process, it will kill all its child process as well.

Upvotes: 1

Related Questions