5

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.

Alphaceph
  • 115
  • 1
  • 10

4 Answers4

1

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?

aid
  • 136
  • 3
  • The point is that when in a function, if you do not declare a variable as global then python will create a local variable with the same name, rather than accessing the global variable. – Dunes Aug 14 '11 at 10:33
  • ya I did explicitly say it as global. But the kill() is not working. – Alphaceph Aug 14 '11 at 11:36
0

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?).

Wissam Youssef
  • 800
  • 1
  • 10
  • 20
0

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
Pykler
  • 14,565
  • 9
  • 41
  • 50
  • I have similar code to yours. I found the problem now, it was the p.kill() which is not killing the correct process. I will update my post to reflect this. – Alphaceph Aug 15 '11 at 10:46
  • By Any chance, are you catching all exceptions in your code using a bare except, like so try: somecode() except: somehanding() you should always, use except Exception: ... if you want to catch all, because a bare except will also catch a SIGINT. – Pykler Aug 24 '11 at 13:07
0

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

Alphaceph
  • 115
  • 1
  • 10