wx.Process crashing app on Linux

I had no problems with the code and technique below on MS-Win but on
Linux application is getting crashed.

I need to execute two external commands in an order and capture their
output. Once processes are launched, control should immediately come
back to GUI so that it should be responsive instead of waiting for
process two finish.

Process one is merely taken 0.5-1.0 second to finish where as process
2 is taking couple of seconds. Until process 1 is not finished process
2 should not start. For this I have used
wx.EXEC_SYNC for prcess1 and wx.EXEC_ASYNC for process 2.

The process class:

class Process(wx.Process):

    """"""

    def __init__(self, sync=False):

        wx.Process.__init__(self)

        self.timer = wx.Timer(self)

        self.Redirect()

        self.Bind(wx.EVT_TIMER, self.OnTimer)

        self.sync = sync

        self.pid = None

    def Start(self, cmd):

        """"""

        if self.sync:

            self.pid = wx.Execute(cmd, wx.EXEC_SYNC, self)

        else:

            self.pid = wx.Execute(cmd, wx.EXEC_ASYNC, self)

        self.timer.Start(200)

    def Stop(self):

        """"""

        if self.pid != None:

            try:

                self.Kill(self.pid, sig=wx.SIGKILL)

                time.sleep(0.5)

            except:

                print "Unable to stop"

    def OnTerminate(self, pid, status):

        """"""

        # First empty pending outputs then stop the timer.

        self.OnTimer(None)

        self.timer.Stop()

        self.pid = None

    def OnTimer(self, event):

        """"""

        stream = self.GetErrorStream()

        if stream.CanRead():

            text = stream.read().strip()

            # show text

calling code:

if self.process1 != None:

        process1.Stop()

self. process1 = Process(sync=True)

self.process1.Redirect()

self.process1.Start(cmd1)

# prepare cmd and data for process 2 here

if self.process2 != None:

   self.process2.Stop()

self.process2 = Process()

self.process2.Redirect()

        try:

            self.process2.Start(cmd2)

        except Exception, e:

            # show error msg here.

On Linux, first time both the process are executing, when executing
again,

if self.process1 != None:
        process1.Stop()

This is causing application to crash without any warning or error.
AFAIK this is the easiest
way to manage the job but are their any other safe methods available?
Or there is something seriously wrong in the code above?

Prashant

#---- System Information ----#
GUI2Exe Version: 0.5.0
Operating System: Linux 2.6.31-14-generic i686
Python Version: 2.6.4rc2 (r264rc2:75497, Oct 20 2009, 02:55:11)
[GCC 4.4.1]
wxPython Version: 2.8.10.1 (gtk2-unicode)
wxPython Info: (__WXGTK__, wxGTK, unicode, gtk2, wx-assertions-off,
SWIG-1.3.29)
Python Encoding: Default=UTF-8 File=UTF-8
wxPython Encoding: utf-8
System Architecture: 32bit i686
Byte order: little
Frozen: False
#---- End System Information ----#

The only thing I notice is that Redirect ends up being called twice because you are calling it in __init__ and also after you've created your process objects, but I wouldn't expect that to cause this kind of problems.

You may want to look at the subprocess module for an alternative.

···

On 2/10/10 3:34 AM, King wrote:

I had no problems with the code and technique below on MS-Win but on
Linux application is getting crashed.

I need to execute two external commands in an order and capture their
output. Once processes are launched, control should immediately come
back to GUI so that it should be responsive instead of waiting for
process two finish.

Process one is merely taken 0.5-1.0 second to finish where as process
2 is taking couple of seconds. Until process 1 is not finished process
2 should not start. For this I have used
wx.EXEC_SYNC for prcess1 and wx.EXEC_ASYNC for process 2.

The process class:

class Process(wx.Process):

     """"""

     def __init__(self, sync=False):

         wx.Process.__init__(self)

         self.timer = wx.Timer(self)

         self.Redirect()

         self.Bind(wx.EVT_TIMER, self.OnTimer)

         self.sync = sync

         self.pid = None

     def Start(self, cmd):

         """"""

         if self.sync:

             self.pid = wx.Execute(cmd, wx.EXEC_SYNC, self)

         else:

             self.pid = wx.Execute(cmd, wx.EXEC_ASYNC, self)

         self.timer.Start(200)

     def Stop(self):

         """"""

         if self.pid != None:

             try:

                 self.Kill(self.pid, sig=wx.SIGKILL)

                 time.sleep(0.5)

             except:

                 print "Unable to stop"

     def OnTerminate(self, pid, status):

         """"""

         # First empty pending outputs then stop the timer.

         self.OnTimer(None)

         self.timer.Stop()

         self.pid = None

     def OnTimer(self, event):

         """"""

         stream = self.GetErrorStream()

         if stream.CanRead():

             text = stream.read().strip()

             # show text

calling code:

  if self.process1 != None:

         process1.Stop()

self. process1 = Process(sync=True)

self.process1.Redirect()

self.process1.Start(cmd1)

# prepare cmd and data for process 2 here

if self.process2 != None:

    self.process2.Stop()

  self.process2 = Process()

  self.process2.Redirect()

         try:

             self.process2.Start(cmd2)

         except Exception, e:

             # show error msg here.

On Linux, first time both the process are executing, when executing
again,

  if self.process1 != None:
         process1.Stop()

This is causing application to crash without any warning or error.
AFAIK this is the easiest
way to manage the job but are their any other safe methods available?
Or there is something seriously wrong in the code above?

--
Robin Dunn
Software Craftsman

Considering above code, how do you set up two processes in such a way
that until first is not finished, second one should not start:

pseudo code:

self.process1.Start(cmd1)
wait for process1 to finish
self.process2.Start(cmd2)

One way is to insert a while loop after first process starts and
continuously checking with a condition like:

while(False)
    return self.process1.IsRunning()

I don't know if it's work or there is better alternative available and
secondly I am bit unsure about methods to check, if a process is
running?

Thanks

Prashant

Did you look at the subprocess module's docs? They clearly state that
all you need to do is this:

subprocess.call() or subprocess.Popen().wait()

Note that if you do this inside wx, your application will probably
become unresponsive. I would recommend calling those in a thread.

···

On Mar 10, 3:13 am, King <animator...@gmail.com> wrote:

Considering above code, how do you set up two processes in such a way
that until first is not finished, second one should not start:

pseudo code:

self.process1.Start(cmd1)
wait for process1 to finish
self.process2.Start(cmd2)

One way is to insert a while loop after first process starts and
continuously checking with a condition like:

while(False)
return self.process1.IsRunning()

I don't know if it's work or there is better alternative available and
secondly I am bit unsure about methods to check, if a process is
running?

Thanks

Prashant

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

wx.Process has one advantage over using the subprocess module that makes it more helpful in this case, and that is the ability to send an event when the process terminates. So basically you can create a process object, bind a handler to it for the wx.EVT_END_PROCESS event, start the process running, and then simply return from the current event handler to the main loop. When the process terminates and you get the event then you can start the 2nd process.

···

On 3/10/10 7:26 AM, Mike Driscoll wrote:

On Mar 10, 3:13 am, King<animator...@gmail.com> wrote:

Considering above code, how do you set up two processes in such a way
that until first is not finished, second one should not start:

pseudo code:

self.process1.Start(cmd1)
wait for process1 to finish
self.process2.Start(cmd2)

One way is to insert a while loop after first process starts and
continuously checking with a condition like:

while(False)
     return self.process1.IsRunning()

I don't know if it's work or there is better alternative available and
secondly I am bit unsure about methods to check, if a process is
running?

Thanks

Prashant

Did you look at the subprocess module's docs? They clearly state that
all you need to do is this:

subprocess.call() or subprocess.Popen().wait()

subprocess — Subprocess management — Python 3.13.0 documentation

Note that if you do this inside wx, your application will probably
become unresponsive. I would recommend calling those in a thread.

--
Robin Dunn
Software Craftsman

I gave a try but bind function is never getting called. For example:

self. process1 = Process(sync=True)
self.process1.Bind(wx.EVT_END_PROCESS, self.onFinish)

self.onFinish is never getting called.

The another option is to throw a custom event from "OnTerminate"
function, which is getting called automatically.

Prashant

If you are overriding OnTerminate and also trying to catch the event then it is expected to fail since IIRC the default OnTerminate is where the event is being sent from. If that is not the case then something is wrong. Does the event handler in the Process sample in the demo get called if you click the Close Stream button? (It will write a message to the log.)

···

On 3/11/10 8:05 PM, King wrote:

I gave a try but bind function is never getting called. For example:

self. process1 = Process(sync=True)
self.process1.Bind(wx.EVT_END_PROCESS, self.onFinish)

self.onFinish is never getting called.

The another option is to throw a custom event from "OnTerminate"
function, which is getting called automatically.

--
Robin Dunn
Software Craftsman

Well, everything is solved. I found a great script over here:

http://www.koders.com/python/fidC03EBAB6F160F7F21AF8AE989153F0AF62DA5DDB.aspx?s=self#L7

Yes, OnTerminate was overridden and at the the same time I was trying
to catch end_process event.

Thanks

Prashant