Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to kill a pid [SOLVED]
#1
Hi,

I'm trying to stop a wav file from playing when a button is pressed but I just cannot get it right.

Any help is appeciated. This' my test code:

#!/usr/bin/python

import commands, os, signal, time
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library

pushbutton = 23
buttonstate = True

GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BCM) # Use physical pin numbering
GPIO.setup(pushbutton, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set pin 10 to be an input pin and set initial value to be pulled low (off)

p = os.getpid()
file = 'music.wav'

def song():
    command = 'mplayer -softvol -volume 5 %s 1>/dev/null 2>&1' % file
    os.system(command)

def kill():
    buttonstate = GPIO.input(pushbutton)
    if buttonstate == False:
      print('Killing pid')
      time.sleep(0.3)
      os.kill(p, signal.SIGKILL)

if __name__ == '__main__':
    song()
    while True:
      kill()
Reply
#2
Use psutil
def killtree(pid, including_parent=True):
    parent = psutil.Process(pid)
    for child in parent.children(recursive=True):
        print "child", child
        child.kill()
    if including_parent:
        parent.kill()  ## this program

pid=os.getpid()
if some_condition:
    killtree(pid)
 
Reply
#3
Thank you, your code worked as well but my main issue is that I want the song to stop playing when the push button is pressed. Now the song only stops when CTR-C and the push button are pressed. My intentions are to eliminate the KB from the loop. Here's the test code modified:

#!/usr/bin/python

import commands, os, psutil, signal, threading, time
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library

pushbutton = 23 #GPIO23
buttonstate = True

GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BCM) # Use GPIO numbering
GPIO.setup(pushbutton, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set line as input pin and set initial value to be pulled high (on)

file = 'music.wav'

def song():
    command = 'mplayer -softvol -volume 4 %s 1>/dev/null 2>&1' % file
    os.system(command)

def killtree(pid, including_parent = True):
    parent = psutil.Process(pid)
    for child in parent.children(recursive = True):
        print "child", child
        child.kill()
    if including_parent:
        parent.kill()  ## this program

if __name__ == '__main__':
    
    song()
    
    while True:
      buttonstate = GPIO.input(pushbutton)
      pid = os.getpid()
      if buttonstate == False:
        print('Killing pid')
        time.sleep(0.3) #debounce delay
        killtree(pid)
Reply
#4
You continually overlay the variable pid under the while True. os.getpid returns the last pid started, and if some system or other program started later, then you are killing that program. Call os.getpid() once as the very first statement executed in the program.

I do not know if you can kill an os.system process (I don't use it). You can kill a subprocess process (see POpen kill at https://pymotw.com/3/subprocess/index.html ). I personally prefer multiprocessing (see Terminating Processes at https://pymotw.com/3/multiprocessing/bas...-processes ).
""" this uses psutil
.  It can also be used
"""

import multiprocessing
import os
import psutil
import time


def killtree(pid, including_parent=True):
    parent = psutil.Process(pid)
    for child in parent.children(recursive=True):
        print("child", child)
        child.kill()
    if including_parent:
        parent.kill()  ## this program

def print_numbers():
    ctr = 0
    for x in range(1000):
        ctr +=1
        print ctr
        time.sleep(0.5)

pid=os.getpid()

## substitute mplayer here
mp = multiprocessing.Process(target=print_numbers)
mp.start()
p= psutil.Process(mp.pid)
print 'pid =', pid, p
print "status", mp.is_alive()

time.sleep(5)
if mp.is_alive():
     print("terminate")
     mp.terminate()
     mp.join()
else:
    print "already terminated"
print 'pid =', pid, p
print "status", mp.is_alive()
killtree(pid)
Reply
#5
Well, the wav file is hard to kill. It only dies with CTR-C which I cannot use.
Your code returns the python pid and not the mplayer's.

This' the modified code:

import multiprocessing
import os
import psutil
import time
from subprocess import check_output

file = 'music.wav'

def killtree(pid, including_parent=True):
    parent = psutil.Process(pid)
    for child in parent.children(recursive=True):
        print("child", child)
        child.kill()
    if including_parent:
        parent.kill()  ## this program

def song():
    command = 'mplayer -softvol -volume 1 %s 1>/dev/null 2>&1' % file
    os.system(command)


pid=os.getpid() ##this sketch's pid!!

mp = multiprocessing.Process(target=song)
mp.start()

p= psutil.Process(mp.pid)
print 'pid =', pid, p
print "status", mp.is_alive()
 
time.sleep(0.5)
if mp.is_alive():
     print("terminate")
     mp.terminate()
     mp.join()
else:
    print "already terminated"
    print 'pid =', pid, p
    print "status", mp.is_alive()

killtree(pid)
Reply
#6
Can't help you further as you insist on using os.system, instead of subprocess of multiprocessing, which I know nothing about
Reply
#7
Thanks for introducing me to multiprossesing. I finally got it working. Not sure if it's the best way of doing it but here's my final code.

import RPi.GPIO as GPIO
import time, os, signal, playsong
from multiprocessing import Process
from subprocess import check_output

buttonpin = 23 #GPIO23

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(buttonpin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

m_pid = 0

def play():
    '''play music from playsong.py '''
    playsong.song()

def get_pid():
    '''gets mplayer's actual pid'''
    global m_pid
    m_pid = int(check_output(["pidof","-s","mplayer"]))
    print "mplayer's pid: ", m_pid

def kill_pid(pid):
    '''used to kill mplayer's pid'''
    os.kill(pid, signal.SIGKILL)

def button():
    '''check if button is pressed'''
    while True:
        input_state = GPIO.input(buttonpin)
        if input_state == False:
            print 'on'
            time.sleep(0.3) #debounce
            kill_pid(m_pid)

if __name__ == '__main__':
  p1 = Process(target=play)
  p1.start()
  p2 = Process(target=button)
  p2.start()
  p3 = Process(target=get_pid)
  p3.start()
  p1.join()
  p2.join()
  p3.join()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  kill python execution program lebossejames 0 184 Mar-16-2024, 11:16 AM
Last Post: lebossejames
  How to immediately kill and restart a thread while using a time.sleep() inside it? philipbergwerf 4 3,452 Feb-07-2022, 04:16 PM
Last Post: Gribouillis
  Using a button to kill and restart a script duckredbeard 3 3,247 Sep-01-2020, 12:53 AM
Last Post: duckredbeard
  how to check for thread kill flag nanok66 1 2,150 May-09-2020, 10:06 PM
Last Post: nanok66
  kill thread or process asap, even during time.sleep nanok66 4 2,868 Apr-29-2020, 10:13 AM
Last Post: nanok66
  Linux: Automatically kill process with fixed exe path anddontyoucomebacknomore 4 2,974 Apr-22-2019, 07:35 AM
Last Post: anddontyoucomebacknomore

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020