--_ea4a0bb7-cdbe-402a-9c19-2b928ec0f020_
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable


Well, I'm sure I have nowhere as good an idea of PTY.spawn() as Matsumotooes, but let me try to explain what your code is doing, and how to get your desired result.

First, you might want to consider using other methods for what you're doing. You probably don't really need a pseudo terminal, which is what PTY gives you, and you can use more well documented methods. These two links give a good overview of some of the other ways you can start subprocesses inuby:
http://devver.net/blog/2009/06/a-dozen-or-so-ways-to-start-sub-processes-in-ruby-part-1/
http://devver.net/blog/2009/07/a-dozen-or-so-ways-to-start-sub-processes-in-ruby-part-2/

If you still think you really need to use a pseudo terminal, then read on.

PTY.spawn() doesn't block your ruby program like a call to system() would. It simply starts the process given the command, and lets you continue. Inour first email, you mentioned that when you took out the "sleep 10" line in your code, no exception took place at all. The reason for this is that your script ended before the child did, since the ten seconds of sleep were taken out. And so ruby did not have a chance to raise an exception. Similarly, in your latest code example, "TEST END" was never printed because the
begin block had an exception before you even reached the 'printf "TEST END\n"' line. The exception occurred while
it was in "sleep 10".  I hope that's clear, it messed me up too in the past.

To get what you want, you might want to use the block form for PTY.spawn() instead. I just find it cleaner, and using the limited scope for the variables pipe_read etc makes sense. The variables are gone when the pseudo terminal is gone.

What I've done is put a loop inside the PTY.spawn() block, which can be used to handle the output from the subprocess, or feed it input. If you don't need to do that, you probably don't need to use PTY anyways, but you can be the judge of that. Now, this loop stops when the subprocess exits, and then the rest of the ruby script continues.

It seems like you also want to run some code in parallel to the subprocess, but not in the loop I mentioned. For this case, the code below also has a thread. Only when the child exits does the thread stop, and "t.join"inally allows the code to continue. Before "t.join" and after the thread block though, you can run code in parallel to the subprocess. And then,Test End" is printed after the subprocess has exited. Here's the code:

require 'pty'

cmd = "/home3/cman/work/product/integrator/test/syb2/OCS-15_0/bin/isql -Uuser2 -Puser2 -Scman2"

t = Thread.new do
  begin
    PTY.spawn(cmd) do |pipe_read, pipe_write, pid|
      loop do
        # Code here can handle output given by your command, and feed it input, etc
        # But the infinite loop will be broken by the exception caused whenhe child process exits, and your script continues
        # Or you could just terminate this loop in advance, but remember, you might reach the end of your ruby script
        # before the child exits, in case that's a problem.
      end
    end
  rescue PTY::ChildExited => msg
    puts "The child has exited"
  rescue => msg
    puts "A different exception:\n" + msg
  end
end

puts "Doing stuff in parallel to the subprocess here"
t.join
puts "Test End"


I hope that was useful/clear. It was certainly too long.

- Ehsan


> Date: Fri, 11 Sep 2009 09:56:15 +0900
> From: denis.berezhnoy / gmail.com
> Subject: Re: Can not catch PTY::ChildExited exception
> To: ruby-talk / ruby-lang.org
> 
> Yukihiro Matsumoto wrote:
> > Hi,
> > 
> > In message "Re: Can not catch PTY::ChildExited exception"
> >     on Wed, 9 Sep 2009 15:14:09 +0900, Denis Berezhnoy 
> > <denis.berezhnoy / gmail.com> writes:
> > 
> > |I have problem that I can not catch PTY::ChildExited exception. Here is
> > |the code:
> > 
> > The exception was raised when the child process terminated
> > (asynchronously), so you need to wrap not only spawn but everything.
> > 
> >               matz.
> 
> Hello Matsumoto-san,
> 
> Thank you very much for clarifications! I tried to wrap around whole 
> code with begin rescue block and I can catch ChildExited exception.  So 
> now I have code like this:
> 
> require 'pty'
> 
> cmd = "/home3/cman/work/product/integrator/test/syb2/OCS-15_0/bin/isql 
> -Uuser2 -Puser2 -Scman2"
> 
> begin
> 
> pipe_read, pipe_write, pid = PTY.spawn(cmd)
> 
> sleep 10
> 
> printf "TEST END\n"
> 
> rescue PTY::ChildExited => msg
>     puts "Caught child exited exception!"
> rescue => msg
>     puts "Caught exception!"
> rescue => e
>     puts e.msg
>     puts e.type
> end
> 
> 
> But now the problem is that ChildExited exception can occur at any 
> moment after spawn and interrupt program in random place. In my test 
> above I never get TEST END printed.
> 
> How can I handle this in right way?
> 
> Best regards,
> Denis
> -- 
> Posted via http://www.ruby-forum.com/.
> 

_________________________________________________________________
With Windows Live, you can organize, edit, and share your photos.
http://www.windowslive.com/Desktop/PhotoGallery-_ea4a0bb7-cdbe-402a-9c19-2b928ec0f020_--