2

I have a python code as following:

import threading
import time
import subprocess, os, sys, psutil, signal
from signal import SIGKILL

def processing():
    global p_2
    global subp_2
    .
    .
    .
    if condition1: #loop again
          threading.Timer(10,processing).start()
    if condition2:
          signal.signal(signal.SIGINT, signal_handler)
          #signal.signal(signal.SIGTERM, signal_handler)
          subp_2.terminate()   
          #os.kill(subp_2.pid, 0)
          #subp_2.kill()            
          print " Status p_2: ", p_2.status

def signal_handler(signal, frame):
    print('Exiting')
    sys.exit(0)

def function():
    global p_1
    global subp_1
    .
    .
    .
    if condition1: #loop again
          threading.Timer(5,function).start()

    if condition2:

          signal.signal(signal.SIGINT, signal_handler)
          #signal.signal(signal.SIGTERM, signal_handler)
          subp_1.terminate()   
          #os.kill(subp_1.pid, 0)
          #subp_1.kill()            
          print " Status p_1: ", p_1.status
          threading.Timer(10,processing).start()  
          subp_2 =  subprocess.Popen('./myScript2.sh %s %s' % (arg0, arg1), shell=True)
          p_2 = psutil.Process(subp_2.pid)

if __name__ == '__main__':
          global p_1
          global subp_1 
          .
          .
          .
          subp_1 = subprocess.Popen(["/.../myScript1.sh"],  shell=True)
          p_1 = psutil.Process(subp_1.pid)
          threading.Timer(5,function).start()

I could not kill the processe subp_1 and subp_2. Whatever I tried: .terminate(), .kill() or os.kill() I am still getting process status running. Could anyone tell me please what am I missing ? Any hint is appreciated.

1 Answer 1

4

When you use shell=True, first a subprocess is spawned which runs the shell. Then the shell spawns a subprocess which runs myScript2.sh. The subprocess running the shell can be terminated without terminating the myScript2.sh subprocess.

If you can avoid using shell=True, then that would be one way to avoid this problem. If using user input to form the command, shell=True should definitely be avoided, since it is a security risk.

On Unix, by default, the subprocess spawned by subprocess.Popen is not a session leader. When you send a signal to a session leader, it is propagated to all processes with the same session id. So to have the shell pass the SIGTERM to myScript2.sh, make the shell a session leader.

For Python versions < 3.2 on Unix, that can be done by having the shell process run os.setsid():

import os
subp_2 =  subprocess.Popen('./myScript2.sh %s %s' % (arg0, arg1), 
                           shell=True, 
                           preexec_fn=os.setsid)

# To send SIGTERM to the process group:
os.killpg(subp_2.pid, signal.SIGTERM)

For Python versions >= 3.2 on Unix, pass start_new_session=True to Popen.

For Windows, see J.F. Sebastian's solution.

Sign up to request clarification or add additional context in comments.

6 Comments

thanks, and how to terminate, or kill sub_p2 ? I've tried os.kill(subp_listenSlave.pid, 0) but the status is sleeping, If I use subp_2.terminate() and put time.sleep(0.5) after, the status is zombie
Whenever I define in the main function signal.signal(signal.SIGTERM, signal_handler) I got: AttributeError: 'bool' object has no attribute 'SIGTERM'
This is saying that somewhere in the main function you are redefining signal to equal a bool.
Note also that using signal.signal is not the best way to implement timeouts. Consider using jcollado's Command class instead.
yes I find the redefinition, my bad. However I am still getting zombie status after executing exactly what you told me to do.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.