I've written small gui-frontend in Python that lets users play internet radio channels. The program uses Pythons subprocess() to initizalize mplayer in order to tune into a channel, e.g.:
runn = "mplayer http://77.111.88.131:8010"
p = subprocess.Popen(runn, shell=True)
pid = int(p.pid)
wait = os.waitpid(p.pid, 1)
Then saves p.pid, and when a user wants to stop listening the following code is used:
os.kill(p.pid, 9)
This works perfectly in OpenSUSE, but not in Ubuntu. It seems that Ubuntu actually starts two separate processes. Terminal output:
Opensuse 11.3:
$ pgrep mplayer
22845
Ubuntu 10.04:
$ pgrep mplayer
22846
22847
This also applies when running other programs. Does anyone know why? I really want this app to run on all distros, so any help is deeply appreciated.
I don't have an exact answer, but here are several ways to investigate:
Use
pstree
to examine the parent/child relationship between the processes.Use
ps -awux
to view the full the command line arguments for all of the processes.Note that using
shell=True
starts a shell process (e.g.,/bin/bash
) which startsmplayer
. That might be another avenue for investigation. Are both systems using the same shell?Are both systems using the same version of mplayer? of python?
Try this:
My guess as to what's going on is this...
When you say
shell=True
subprocess actually starts this commandsh -c "your string"
. Thesh
command then interprets your string and runs the command as if you'd typed that in at the shell prompt (more or less). Normally this would result in two processes. One would besh -c "your string"
and the other would be it's child,your string
.Some versions of
sh
have an optimization in which they will automaticallyexec
the command under certain conditions. They do it if it's the last commandsh
is going to run andsh
has no other reason to stick around. When usingsh -c
to run a command, this will almost always result in that invocation ofsh
replacing itself with the command it's running, thereby resulting in one process.In my opinion it's a really, really bad idea to ever invoke
subprocess.Popen
withshell=True
. You are opening yourself up for a ton of security issues by doing that, and generally less predictable behavior because shell metacharacters are interpreted bysh -c
.subprocess.Popen returns a Popen object with several useful methods. It's probably a bad idea to terminate things by directly using os.kill...
Does the same thing happen if you use the Popen object's p.terminate() or p.kill() methods?