[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to exit properly with a signal?

bob

10/10/2004 12:45:00 AM

How are signals properly handled in ruby? (I am new to ruby but
experienced with C, sh and perl.)

Run, then interrupt it while it is in the sleep:

sh -c 'sleep 10' ; echo $?

130

However, this same script in ruby is trapped by the ruby default
signal handler.

ruby -e 'sleep 10' ; echo $?
-e:1:in `sleep': Interrupt from -e:1
1

How may I have ruby's program exit code properly reflect to the caller
that it was terminated on a signal? And also how may I prevent the
default handler from printing extraneous information?

The perl version behaves as desired here similar to the shell version.

perl -e 'sleep 10' ; echo $?

130

I want to replace some existing programs with ruby equivalents.
I am using ruby 1.8.2 from Debian sid/unstable.

Thanks
Bob


4 Answers

gabriele renzi

10/10/2004 2:16:00 AM

0

Bob Proulx ha scritto:

> How are signals properly handled in ruby? (I am new to ruby but
> experienced with C, sh and perl.)
>
> Run, then interrupt it while it is in the sleep:
>
> sh -c 'sleep 10' ; echo $?
>
> 130
>
> However, this same script in ruby is trapped by the ruby default
> signal handler.
>
> ruby -e 'sleep 10' ; echo $?
> -e:1:in `sleep': Interrupt from -e:1
> 1
>

I guess you want:
trap("INT") { puts "interrupted" }

bob

10/10/2004 4:01:00 AM

0

gabriele renzi wrote:
> Bob Proulx ha scritto:
> > ruby -e 'sleep 10' ; echo $?
> > -e:1:in `sleep': Interrupt from -e:1
> > 1
>
> I guess you want:
> trap("INT") { puts "interrupted" }

Thank you for your reply. Unfortunately that does not work either.
Run, then interrupt:

ruby -e 'trap("INT") { } ; sleep 10' ; echo $?
0

The return code is now zero indicating a successful program
completion. Of course I can exit with an error in the handler such as
in the following example.

ruby -e 'trap("INT") { exit 1 } ; sleep 10' ; echo $?
1

But again, this does not return the proper wait(2) status to the
caller. The caller can't tell that the child process was terminated
with a signal.

In perl one does the following:

$SIG{$sig} = 'DEFAULT';
kill($sig,$$);

In C one does the following:

act.sa_flags = 0;
act.sa_handler = SIG_DFL;
sigaction(sig,&act,0);
raise(sig);

I tried doing in ruby what I would do in perl. Basically the
following.

trap sig, "DEFAULT"
Process.kill sig, $$

But no joy. Again my efforts were not able to produce the required
results.

ruby ./signals.rb ; echo $?
starting program
signal INT received, cleaning up
./signals.rb:5:in `sighandler': Interrupt from ./signals.rb:7
from ./signals.rb:7:in `call'
from ./signals.rb:9:in `sleep'
from ./signals.rb:9
1

How can I exit with the same wait(2) status as if the program was
terminated on a signal? Hopefully someone will know the solution to
this problem.

Thanks
Bob


Charles Mills

10/10/2004 5:29:00 AM

0

On Oct 9, 2004, at 5:45 PM, Bob Proulx wrote:

> How are signals properly handled in ruby? (I am new to ruby but
> experienced with C, sh and perl.)
>

Here is a stab in the dark... how about this:
$ ruby -e 'trap("INT") { |s| exit(s) }; sleep 10'; echo $?
^C2
$
or this:
$ ruby -e 'trap("INT") { |s| exit(128 + s) }; sleep 10'; echo $?
^C130
$

Works like bash, seems to be what you want...
---- taken from bash man page:
For the shell's purposes, a command which exits with a zero exit
status
has succeeded. An exit status of zero indicates success. A
non-zero
exit status indicates failure. When a command terminates on a
fatal
signal N, bash uses the value of 128+N as the exit status.
-----------------------------------------

-Charlie

> Run, then interrupt it while it is in the sleep:
>
> sh -c 'sleep 10' ; echo $?
>
> 130
>
> However, this same script in ruby is trapped by the ruby default
> signal handler.
>
> ruby -e 'sleep 10' ; echo $?
> -e:1:in `sleep': Interrupt from -e:1
> 1
>
> How may I have ruby's program exit code properly reflect to the caller
> that it was terminated on a signal? And also how may I prevent the
> default handler from printing extraneous information?
>
> The perl version behaves as desired here similar to the shell version.
>
> perl -e 'sleep 10' ; echo $?
>
> 130



Lloyd Zusman

10/10/2004 6:21:00 AM

0

Charles Mills <cmills@freeshell.org> writes:

> On Oct 9, 2004, at 5:45 PM, Bob Proulx wrote:
>
>> How are signals properly handled in ruby? (I am new to ruby but
>> experienced with C, sh and perl.)
>>
>
> Here is a stab in the dark... how about this:
> $ ruby -e 'trap("INT") { |s| exit(s) }; sleep 10'; echo $?
> ^C2
> $
> or this:
> $ ruby -e 'trap("INT") { |s| exit(128 + s) }; sleep 10'; echo $?
> ^C130
> $
>
> Works like bash, seems to be what you want...

This works, but is it possible within the signal handler to get a
Process::Status object for the current program? If so, we could
return the status in the Posix-compliant way that 'sh' and 'perl'
do so.

The following comes from the Process::Status documentation:

Process::Status encapsulates the information on the status of a
running or terminated system process. The built-in variable $? is
either nil or a Process::Status object.

fork { exit 99 } #=> 26557
Process.wait #=> 26557
$?.class #=> Process::Status
$?.to_i #=> 25344
$? >> 8 #=> 99
$?.stopped? #=> false
$?.exited? #=> true
$?.exitstatus #=> 99

Posix systems record information on processes using a 16-bit
integer. The lower bits record the process status (stopped, exited,
signaled) and the upper bits possibly contain additional information
(for example the program's return code in the case of exited
processes). Pre Ruby 1.8, these bits were exposed directly to the Ruby
program. Ruby now encapsulates these in a Process::Status object. To
maximize compatibility, however, these objects retain a bit-oriented
interface. In the descriptions that follow, when we talk about the
integer value of stat, we're referring to this 16 bit value.

If we could interrogate the `$?' object (i.e., a Process::Status
instance) within a signal handler, we could do this:

ruby -e 'trap("INT") { |s| exit($?.to_i) }; sleep 10'; echo $?

It would return 130.

However, in this case, `$?' is set to nil within the signal trap. In a
signal handler, is there a way to cause it to be set to the current
process's status? Or does it only get set after the return of a
Process.wait call that catches the exit of another forked process?



> ---- taken from bash man page:
> For the shell's purposes, a command which exits with a zero exit
> status
> has succeeded. An exit status of zero indicates success. A
> non-zero
> exit status indicates failure. When a command terminates on a
> fatal
> signal N, bash uses the value of 128+N as the exit status.
> -----------------------------------------
>
> -Charlie
>
>> Run, then interrupt it while it is in the sleep:
>>
>> sh -c 'sleep 10' ; echo $?
>>
>> 130
>>
>> However, this same script in ruby is trapped by the ruby default
>> signal handler.
>>
>> ruby -e 'sleep 10' ; echo $?
>> -e:1:in `sleep': Interrupt from -e:1
>> 1
>>
>> How may I have ruby's program exit code properly reflect to the caller
>> that it was terminated on a signal? And also how may I prevent the
>> default handler from printing extraneous information?
>>
>> The perl version behaves as desired here similar to the shell version.
>>
>> perl -e 'sleep 10' ; echo $?
>>
>> 130
>
>
>

--
Lloyd Zusman
ljz@asfast.com
God bless you.