Question

I have problem killing sub processes. The following piece of code is used for creating the sub process-

  while(not myQueue.empty()): 
        p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)

I'm creating processes by iterating until the queue(which has commands in it) is empty. The variable p is global and is an object of type Popen. Even though the command has done what it is supposed to do, I'm having problems with stop button which is not stopping the process as I expected.

The stop button code is as follows-

  stop=Button(textBoxFrame,text="Stop",width=5,command=stopAll)
  stop.grid(row=1,column=4)

The stopAll method is called by the above stop button which will kill the current subprocess p.

  def stopAll():
        p.kill()

NOTE-There are no errors, Exceptions or any compiling problems.

UPDATE: The problem is that p.kill() was not killing the process I needed to kill. I checked this with unix using >> ps aux. I have also made my program to output starting and killing PIDs, so that I can check them with ps aux. I found the process that I need to kill was 6 PIDs away from p.pid, I tried killing the process like os.kill((p.pid)+6,signal.SIGKILL) which is working and stopping the correct process. But I don't want to do in that way as there are chances that may cause different child processes getting killed. I'm giving more details on my problem-

The Queue I'm using here contains commands as I said earlier. The command is something like this-

    echo "Hello"|festival --tts

Festival is a speech synthesizer in unix and festival --tts gets user input from a file. I'm piping "Hello" to festival and it says the words correctly. But p which is the process of performing the above command is killing echo and not festival. So please help me with killing the particular (festival) process.

Was it helpful?

Solution 4

Since the festival program is in UNIX we can make use of preexec_fn. Festival was creating its own sub processes which made killing harder, So in this case making use of group id that identifies all the festival processes will solve it. We can make a group of processes using the code below-

   while(not myQueue.empty()): 
    p=Popen(myQueue.get(),shell=True, stdin=PIPE,preexec_fn=os.setsid)

stopAll now has the following code for killing group of child processes pointed by global variable p-

    os.killpg(os.getpgid(p.pid), signal.SIGKILL)

will kill the group of sub processes that are spawned. Source: Working with subprocess

OTHER TIPS

I suspect you may be having issues as you're not declaring stopPressed inside your stopAll() function as global, by example,

>>> fred = '20'
>>> def updateFred(age):
...     fred=age
>>> updateFred(40)
>>> fred
'20'
>>> def updateFred(age):
...     global fred
...     fred=age
>>> updateFred(40)
>>> fred
40

Perhaps adding 'global stopPressed' at the start of stopAll() will help?

I think more code is needed. I am not sure how you are handling the event of the button being pressed (suspecting a threading problem). Also, shouldn't be stopprcs be included inside the first loop instead of outside? spacing problem (or is the problem just in here?).

As @aid mentioned, ifyou do not explicity make the handle a global you cannot change it for everyone else. Try this instead of your stopAll function

def stopAll():
    global stopPressed
    stopPressed=True

I would suggest instead of messing with globals and what not is to create a class, such as

class GuiController(object):
    # if you want the stopPressed to be a static variable accross all
    # GuiController instances uncomment the next line and comment out the __init__
    #stopPressed = False
    def __init__(self):
        self.stopPressed=False
    def main(self):
        while(not myQueue.empty()): 
            p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)
            while(p.returncode==None):
                if(stopPressed==True):
                    p.kill()
                    break
        self.stopPressed=False
    def stopAll(self):
        self.stopPressed=True
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top