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.

NELOUNI
  • 593
  • 2
  • 6
  • 14

1 Answers1

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.

Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • 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 – NELOUNI Apr 22 '14 at 20:14
  • Whenever I define in the main function signal.signal(signal.SIGTERM, signal_handler) I got: AttributeError: 'bool' object has no attribute 'SIGTERM' – NELOUNI Apr 22 '14 at 20:30
  • This is saying that somewhere in the main function you are redefining `signal` to equal a `bool`. – unutbu Apr 22 '14 at 20:30
  • Note also that using `signal.signal` is [not the best way](http://stackoverflow.com/a/1114567/190597) to implement timeouts. Consider using [jcollado's `Command` class](http://stackoverflow.com/a/4825933/190597) instead. – unutbu Apr 22 '14 at 20:35
  • yes I find the redefinition, my bad. However I am still getting zombie status after executing exactly what you told me to do. – NELOUNI Apr 22 '14 at 20:52
  • Please post a runnable version of your program which demonstrates the problem. – unutbu Apr 22 '14 at 20:57