edjli2005
edjli2005

Reputation: 11

How do you kill a Python subprocess while it's waiting to finish?

Trying to use Python subprocesses to play audio on a Raspberry Pi and kill the subprocess when a GPIO-connected button is pressed.

The issue I'm having is that the subprocess won't kill when there's a subprocess Popen.wait() command between playback files. If there's only one file to play, there's no need to wait for it to finish, and a p.kill() command works just fine. As soon as a p.wait() is inserted so that the files don't play on top of each other, Popen.kill() no longer works.

Already tried using os.kill() in Kill a running subprocess call. Can't find any other resources about how subprocesses behave under Popen.wait(). I'm looking for a way to force the aplay function in the code below to close on a button press at any time during the three play_wav commands in the second code snippet instead of having just one play_wav command.

Here's the play_wav function utilizing subprocess.Popen():

# play wav file on the attached system sound device
def play_wav(wav_filename):
    global p
    msg = "playing " + wav_filename
    logger.debug(msg)
    p = subprocess.Popen(
        ['aplay','-i','-D','plughw:1', wav_filename],
        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        stderr = subprocess.STDOUT,
        shell = False
    )

Here's a snippet of code calling the play_wav function:

# determine what to do when a button is pressed
def button_pressed(channel):
    global MENU
    btnval = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) # check value of ADC
    if btnval > 980: # 1
        if p.poll() == None:
            p.kill()
        if MENU == 1:
            play_wav("/media/pi/WONDERPHONE/prompts/en/Menu1.wav")
            p.wait()
            play_wav("/media/pi/WONDERPHONE/stories/1/PersonalStory.wav")
            p.wait()
            play_wav("/media/pi/WONDERPHONE/prompts/en/returntomain.wav")

How I'm checking for button presses:

GPIO.add_event_detect(PRESSED, GPIO.RISING, callback=button_pressed, bouncetime=500) # look for button presses

Upvotes: 1

Views: 3266

Answers (2)

Rach Sharp
Rach Sharp

Reputation: 2444

From the subprocess module docs:

Popen.wait()

Wait for child process to terminate. Set and return returncode attribute. Warning - This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

Try using communicate() before you kill the subprocess

Upvotes: 1

user8624339
user8624339

Reputation:

You can use terminal to do that. ps aux | grep taskname sudo kill -9 taskid

Upvotes: 0

Related Questions