Hi,
I just wondered why channel switching needs so long on my box and why it is
always accompagnied by a "PANIC can't kill program" message in main-0.log.
Here is what I believe why this is:
Basically, the problem is that os.waitpid and subprocess.Popen.poll do not
really work together. It seems that only one of them can be used, but not
both.
Here are the details:
I have a special plugin for watching TV from DVB-S. This plugin uses a program
(dvbcat) which does not have the possibility to be stopped by some external
command other than sending it a signal.
The plugin controls that program by using childapp.ChildApp. When switching
the channel (or exiting watching TV), it uses childapp.ChildApp.kill to
terminate dvbcat. This means that signal 15 is sent to the program here:
if signal:
_debug_('killing pid %s signal %s' % (self.child.pid, signal), 1)
try:
os.kill(self.child.pid, signal)
except OSError:
pass
After that, the ChildApp.kill uses wait() which in turn uses waitpid().
waitpid() eventually returns True (I believe usually when called the second
time). However, a bit further down in ChildApp.kill(), there is...
for i in range(5):
if self.child.poll() != None:
break
time.sleep(0.1)
At this point in time, the program is already dead (by os.kill and
os.waitpid). self.child.poll() however, always returns None. In the following
coding, the system tries very hard to kill the already killed process.
It seems that the subprocess module does not notice that the process was
killed when os.waitpid was called before. I have written a small tester
program which uses both waitpid and poll in different scenarios. It seems
that only the combinations
os.kill
os.waitpid
or
os.kill
subrocess.Popen.poll
really scurely kill the process and return the correct return value. Maybe in
the time before the subprocess module, os.kill needed the waitpid, but now
just using poll also seems ok, but only without calling waitpid before. I
have the impression that poll() always returns None if waitpid was called
before, regardless wether the process has ended or not.
After finding that out, I wondered why the normal player processes do not have
this problem. Here's what I believe why:
These processes use ChildApp2 and for stopping, the method ChildApp2.stop is
called. This sends some command to the player application and then checks
with isAlive() if the player finished. isAlive in turn just uses poll().
Usually, the player application really quits soon, so isAlive() eventually
returns False and the loop (see below) quits.
if cmd and self.isAlive():
self.write(cmd)
# wait for the app to terminate itself
for i in range(60):
if not self.isAlive():
break
time.sleep(0.1)
After that, kill() is only called when self.isAlive() still is true. Usually,
this is not the case.
I.e. poll() is called without calling waitpid() and usually waitpid() is not
called at all. This is a scenario which really works.
Regards,
Thorsten
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-devel