Trap and multiple occurences

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.
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.

Thanks in advance and best regards,

  Phil

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).

Try this:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

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.

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.

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)

···

Il giorno 05/nov/06, alle ore 02:35, Philipp Taprogge ha scritto:

Thanks in advance and best regards,

  Phil

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

20.times do
   puts "."
   sleep 1
end

Kind regards

  robert

···

On 05.11.2006 02:59, Gabriele Marrone wrote:

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)

Hi!

Thus spake Gabriele Marrone on 11/05/2006 02:59 AM:

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... :wink:

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