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

  • Thread starter Iñaki Baz Castillo
  • Start date
I

Iñaki Baz Castillo

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.

--=20
I=C3=B1aki Baz Castillo
<[email protected]>
 
J

Josh Cheek

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.

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

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

Eric Hodel

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'=
 
R

Robert Klemme

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) {
=A0puts "exiting with status #{status}"
}

if SOMETHING
=A0exit true
else
=A0exit 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 =3D> e
puts "exiting with status #{e.status}"
raise
rescue Exception =3D> e
puts "exiting with status 1"
raise
else
puts "exiting with status 0"
end

Kind regards

robert

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

Iñaki Baz Castillo

2011/2/1 Josh Cheek said:
How about stick your own exit method before Kernel in the lookup chain

class Object
=C2=A0private
=C2=A0def exit(status=3Dtrue)
=C2=A0 =C2=A0at_exit {
=C2=A0 =C2=A0 =C2=A0puts "exiting with status #{status}"
=C2=A0 =C2=A0}
=C2=A0 =C2=A0super
=C2=A0end
end

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.



--=20
I=C3=B1aki Baz Castillo
<[email protected]>
 
I

Iñaki Baz Castillo

2011/2/1 Eric Hodel said:
ruby -e 'at_exit { p $!.status }; exit 1'

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

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

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


--=20
I=C3=B1aki Baz Castillo
<[email protected]>
 
I

Iñaki Baz Castillo

2011/2/1 Robert Klemme said:
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().

First of all: IMHO that is bad practice because it prevents your code
to be used in different situations (i.e. reduces modularity). =C2=A0The
proper way would be to raise exceptions and deal with them
appropriately. =C2=A0You 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
=C2=A0# main code
rescue SystemExit =3D> e
=C2=A0puts "exiting with status #{e.status}"
=C2=A0raise
rescue Exception =3D> e
=C2=A0puts "exiting with status 1"
=C2=A0raise
else
=C2=A0puts "exiting with status 0"
end

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

Thanks a lot.

--=20
I=C3=B1aki Baz Castillo
<[email protected]>
 
E

Eric Hodel

=20
Really interesting. However, it fails if exit() is called outside of = the scope:
=20
irb> at_exit { p "$!.inspect =3D #{$!.inspect}" }
#<Proc:0x000000019f99c0@(irb):1>
irb> exit 1
"$!.inspect =3D nil"
=20
So $! is nil and I cannot get $!.status.

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
 
E

Eric Hodel

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).
=20
For example:
=20
--------------------
at_exit { p "$!.inspect =3D #{$!.inspect}" }
=20
sleep 10
--------------------
=20
If you run this program and press Ctrl+C prior to 10 seconds you get:
=20
"$!.inspect =3D Interrupt"
=20
So, at_exit block is executed but $! is not a SystemExit instance. I
could trap the signals however.

Yes,

if SystemExit =3D=3D=3D $! then =85 end=
 
E

Eric Hodel

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

Yes:

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,129
Latest member
FastBurnketo
Top