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
Freevo-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freevo-devel

Reply via email to