How to know the exit status within at_exit() block?

Hi, my program invokes "exit true" or "exit false" and I want to catch
such return code into at_exit() block, but I don't know how to do
that.

I would like something as:

at_exit(exit_status) {
  puts "exiting with status #{status}"
}

if SOMETHING
  exit true
else
  exit false
end

Of course I call "exit" from lof of clases/modules under my project so
I cannot use a local scope variable "status" (and I wouldn't like to
use a global variable).

Thanks for any suggestion.

···

--
Iñaki Baz Castillo
<ibc@aliax.net>

How about stick your own exit method before Kernel in the lookup chain

class Object
  private
  def exit(status=true)
    at_exit {
      puts "exiting with status #{status}"
    }
    super
  end
end

···

On Mon, Jan 31, 2011 at 5:09 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

Hi, my program invokes "exit true" or "exit false" and I want to catch
such return code into at_exit() block, but I don't know how to do
that.

I would like something as:

at_exit(exit_status) {
puts "exiting with status #{status}"
}

if SOMETHING
exit true
else
exit false
end

Of course I call "exit" from lof of clases/modules under my project so
I cannot use a local scope variable "status" (and I wouldn't like to
use a global variable).

Thanks for any suggestion.

--
Iñaki Baz Castillo
<ibc@aliax.net>

ruby -e 'at_exit { p $!.status }; exit 1'

···

On Jan 31, 2011, at 15:09, Iñaki Baz Castillo wrote:

Hi, my program invokes "exit true" or "exit false" and I want to catch
such return code into at_exit() block, but I don't know how to do
that.

Hi, my program invokes "exit true" or "exit false" and I want to catch
such return code into at_exit() block, but I don't know how to do
that.

I would like something as:

at_exit(exit_status) {
puts "exiting with status #{status}"
}

if SOMETHING
exit true
else
exit false
end

You are aware that you can simplify that to

exit SOMETHING

are you?

Of course I call "exit" from lof of clases/modules under my project so
I cannot use a local scope variable "status" (and I wouldn't like to
use a global variable).

First of all: IMHO that is bad practice because it prevents your code
to be used in different situations (i.e. reduces modularity). The
proper way would be to raise exceptions and deal with them
appropriately. You can even omit the handling on top level and get
appropriate exit codes of the process (i.e. 0 for the regular case, 1
for error):

$ ruby19 -e 'raise "f"'; echo $?
-e:1:in `<main>': f (RuntimeError)
1
$ ruby19 -e 'nil'; echo $?
0
$

However, you can do what you want with a rescue clause:

begin
  # main code
rescue SystemExit => e
  puts "exiting with status #{e.status}"
  raise
rescue Exception => e
  puts "exiting with status 1"
  raise
else
  puts "exiting with status 0"
end

Kind regards

robert

···

On Tue, Feb 1, 2011 at 12:09 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

That could work. Then I need to store status in an Object attribute or
a global variable so I can also check it within at_exit block.

Thanks.

···

2011/2/1 Josh Cheek <josh.cheek@gmail.com>:

How about stick your own exit method before Kernel in the lookup chain

class Object
private
def exit(status=true)
at_exit {
puts "exiting with status #{status}"
}
super
end
end

--
Iñaki Baz Castillo
<ibc@aliax.net>

Hi, my program invokes "exit true" or "exit false" and I want to catch
such return code into at_exit() block, but I don't know how to do
that.

ruby -e 'at_exit { p $!.status }; exit 1'

Really interesting. However, it fails if exit() is called outside of the scope:

at_exit { p "$!.inspect = #{$!.inspect}" }

#<Proc:0x000000019f99c0@(irb):1>

exit 1

"$!.inspect = nil"

So $! is nil and I cannot get $!.status.

···

2011/2/1 Eric Hodel <drbrain@segment7.net>:

--
Iñaki Baz Castillo
<ibc@aliax.net>

You are aware that you can simplify that to

exit SOMETHING

are you?

Yes, but I want to inspect the exit status code into the block
provided to at_exit().

Of course I call "exit" from lof of clases/modules under my project so
I cannot use a local scope variable "status" (and I wouldn't like to
use a global variable).

First of all: IMHO that is bad practice because it prevents your code
to be used in different situations (i.e. reduces modularity). The
proper way would be to raise exceptions and deal with them
appropriately. You can even omit the handling on top level and get
appropriate exit codes of the process (i.e. 0 for the regular case, 1
for error):

$ ruby19 -e 'raise "f"'; echo $?
-e:1:in `<main>': f (RuntimeError)
1
$ ruby19 -e 'nil'; echo $?
0
$

However, you can do what you want with a rescue clause:

begin
# main code
rescue SystemExit => e
puts "exiting with status #{e.status}"
raise
rescue Exception => e
puts "exiting with status 1"
raise
else
puts "exiting with status 0"
end

Using "rescue SystemExit => e" seems indeed appropriate. Let me play a
bit with it.

Thanks a lot.

···

2011/2/1 Robert Klemme <shortcutter@googlemail.com>:

--
Iñaki Baz Castillo
<ibc@aliax.net>

This is completely unrelated to how you _call_ exit. I pointed out
that you can simplify

if SOMETHING
exit true
else
exit false
end

to

exit SOMETHING

or maybe this if you want to ensure the value is boolean

exit !!SOMETHING

Cheers

robert

···

On Wed, Feb 2, 2011 at 11:49 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

2011/2/1 Robert Klemme <shortcutter@googlemail.com>:

You are aware that you can simplify that to

exit SOMETHING

are you?

Yes, but I want to inspect the exit status code into the block
provided to at_exit().

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

>> Hi, my program invokes "exit true" or "exit false" and I want to catch
>> such return code into at_exit() block, but I don't know how to do
>> that.
>
> ruby -e 'at_exit { p $!.status }; exit 1'

Really interesting. However, it fails if exit() is called outside of the
scope:

> at_exit { p "$!.inspect = #{$!.inspect}" }
#<Proc:0x000000019f99c0@(irb):1>
> exit 1
"$!.inspect = nil"

So $! is nil and I cannot get $!.status.

--
Iñaki Baz Castillo
<ibc@aliax.net>

It probably doesn't work in IRB, because IRB wraps calls to exit

method :exit

=> #<Method: Object(IRB::ExtendCommandBundle)#exit>

I think that using $! is probably what you should do.

···

On Wed, Feb 2, 2011 at 4:46 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

2011/2/1 Eric Hodel <drbrain@segment7.net>:

It is irb's fault:

$ cat t.rb
def x
  at_exit { p $!.status }
end

def y
  exit 2
end

x
y
$ ruby t.rb
2

···

On Feb 2, 2011, at 02:46, Iñaki Baz Castillo wrote:

2011/2/1 Eric Hodel <drbrain@segment7.net>:

Hi, my program invokes "exit true" or "exit false" and I want to catch
such return code into at_exit() block, but I don't know how to do
that.

ruby -e 'at_exit { p $!.status }; exit 1'

Really interesting. However, it fails if exit() is called outside of the scope:

> at_exit { p "$!.inspect = #{$!.inspect}" }
#<Proc:0x000000019f99c0@(irb):1>
> exit 1
"$!.inspect = nil"

So $! is nil and I cannot get $!.status.

Ok, perhaps I should clarify that SOMETHING is not the existing status
code but any other kind of condition.

···

2011/2/2 Robert Klemme <shortcutter@googlemail.com>:

Yes, but I want to inspect the exit status code into the block
provided to at_exit().

This is completely unrelated to how you _call_ exit. I pointed out
that you can simplify

if SOMETHING
exit true
else
exit false
end

to

exit SOMETHING

or maybe this if you want to ensure the value is boolean

exit !!SOMETHING

--
Iñaki Baz Castillo
<ibc@aliax.net>

You are right, however I've realized that in case of exiting without
invoking "exit" or "exit!" (i.e. exiting due to a signal) then $! is
not a SystemExit instance, but an Interrupt instance (and it doesn't
have "status" method).

For example:

···

2011/2/2 Josh Cheek <josh.cheek@gmail.com>:

Really interesting. However, it fails if exit() is called outside of the
scope:

> at_exit { p "$!.inspect = #{$!.inspect}" }
#<Proc:0x000000019f99c0@(irb):1>
> exit 1
"$!.inspect = nil"

So $! is nil and I cannot get $!.status.

It probably doesn't work in IRB, because IRB wraps calls to exit

> method :exit
=> #<Method: Object(IRB::ExtendCommandBundle)#exit>

I think that using $! is probably what you should do.

--------------------
at_exit { p "$!.inspect = #{$!.inspect}" }

sleep 10
--------------------

If you run this program and press Ctrl+C prior to 10 seconds you get:

  "$!.inspect = Interrupt"

So, at_exit block is executed but $! is not a SystemExit instance. I
could trap the signals however.

Thanks.

--
Iñaki Baz Castillo
<ibc@aliax.net>

I know.

robert

···

On Wed, Feb 2, 2011 at 12:58 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

2011/2/2 Robert Klemme <shortcutter@googlemail.com>:

Yes, but I want to inspect the exit status code into the block
provided to at_exit().

This is completely unrelated to how you _call_ exit. I pointed out
that you can simplify

if SOMETHING
exit true
else
exit false
end

to

exit SOMETHING

or maybe this if you want to ensure the value is boolean

exit !!SOMETHING

Ok, perhaps I should clarify that SOMETHING is not the existing status
code but any other kind of condition.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Yes,

if SystemExit === $! then … end

···

On Feb 2, 2011, at 06:34, Iñaki Baz Castillo wrote:

You are right, however I've realized that in case of exiting without
invoking "exit" or "exit!" (i.e. exiting due to a signal) then $! is
not a SystemExit instance, but an Interrupt instance (and it doesn't
have "status" method).

For example:

--------------------
at_exit { p "$!.inspect = #{$!.inspect}" }

sleep 10
--------------------

If you run this program and press Ctrl+C prior to 10 seconds you get:

"$!.inspect = Interrupt"

So, at_exit block is executed but $! is not a SystemExit instance. I
could trap the signals however.

Thanks. I wonder if $! can be anything else apart from SystemExit and Interrupt.

···

2011/2/3 Eric Hodel <drbrain@segment7.net>:

If you run this program and press Ctrl+C prior to 10 seconds you get:

"$!.inspect = Interrupt"

So, at_exit block is executed but $! is not a SystemExit instance. I
could trap the signals however.

Yes,

if SystemExit === $! then … end

--
Iñaki Baz Castillo
<ibc@aliax.net>

Yes:

$ ruby -e 'at_exit { p $! }'
nil
$ ruby -e 'at_exit { p $! }; raise'
RuntimeError
-e:1: unhandled exception
$

···

On Feb 3, 2011, at 4:13 AM, Iñaki Baz Castillo wrote:

2011/2/3 Eric Hodel <drbrain@segment7.net>:

If you run this program and press Ctrl+C prior to 10 seconds you get:

"$!.inspect = Interrupt"

So, at_exit block is executed but $! is not a SystemExit instance. I
could trap the signals however.

Yes,

if SystemExit === $! then … end

Thanks. I wonder if $! can be anything else apart from SystemExit and Interrupt.

Great :slight_smile:

···

2011/2/4 Eric Hodel <drbrain@segment7.net>:

$ ruby -e 'at_exit { p $! }'
nil
$ ruby -e 'at_exit { p $! }; raise'
RuntimeError
-e:1: unhandled exception

--
Iñaki Baz Castillo
<ibc@aliax.net>