I am kind of new to ruby so forgive if this is really stupid…
I am experimenting with trapping signals on linux.
It seems like a ruby script can only handle one signal at a time.
While in the trap block, all further occurences of that same signal
are lost.
What I want to do is react differently if a, say, SIGUSR1 comes in
while the script is already in that signal’s trap block.
Is that at all possible?
A bit of background:
A have a script that parses some data and displays it on an external
lcd panel. The panel’s only button can bind a command. I have bound
“kill -SIGUSR1 (pidof myscript.rb)” to it.
Now I want to implement some kind of saveguard where the first press
displays a warning (“are you sure…?”) and the second while still
in the trap actually performs the function.
Il giorno 05/nov/06, alle ore 02:35, Philipp T. ha scritto:
Hi all!
I am kind of new to ruby so forgive if this is really stupid…
I am experimenting with trapping signals on linux.
It seems like a ruby script can only handle one signal at a time.
While in the trap block, all further occurences of that same signal
are lost.
This is not just a ruby issue, it’s the way signal handlers work.
In C if you assign a function to a specific signal with signal(),
that function gets called when the signal is received and the program
flow continues when the function returns. If the same signal is
received while the function is running, it’s ignored (actually, I
think the function gets called again as soon as it returns).
void sighup_handler(int sig)
{
printf("Starting to process signal… ");
fflush(stdout);
sleep(5);
printf(“done.\n”);
}
int main(void)
{
signal(SIGINT, sighup_handler);
sleep(60);
return 0;
}
If you type Ctrl-C two times fast enough, you don’t interrupt the
function sighup_handler() itself.
in the trap actually performs the function.
A very good practice is writing signal handlers that just set a
global variable with the signal(s) received, and then check that
variable and actually do something from within the application main
loop.
There are many good reasons, some are here: http://www-128.ibm.com/
developerworks/linux/library/l-reent.html
(In fact I just googled for a link that explains what I’m thinking,
I’m lazy and sleepy so I didn’t read throughly that page and I hope
it really says what I mean :P)
A very good practice is writing signal handlers that just set a global
variable with the signal(s) received, and then check that variable and
actually do something from within the application main loop.
There are many good reasons, some are here: http://www-128.ibm.com/developerworks/linux/library/l-reent.html
(In fact I just googled for a link that explains what I’m thinking, I’m
lazy and sleepy so I didn’t read throughly that page and I hope it
really says what I mean :P)
The way I’d probably do it is to set up a Queue and have a reader thread
that will process signals placed into the queue. Something along the
lines like this
require ‘thread’
SIG_HANDLER = Queue.new
Thread.new do
while ( sig = SIG_HANDLER.deq )
print "SIGNAL: ", sig.inspect, “\n”
end
end
Signal.list.each do |name, sig|
Signal.trap sig do |s|
SIG_HANDLER.enq s
end
end
This is not just a ruby issue, it’s the way signal handlers work.
Thanks for the explanation and the link.
The days when I learned about unix system programming at the
university are obviously long past…
Well, I did just what you suggested and now handle signals via
global variables that get set/unset with each signal trappen.
That suits my needs since I do not expect too many signals
(keypresses) at once.
Regards,
Phil
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.