Signal handling cross-platform

Hi everyone,

I’m new to Ruby and am coding a program intended to be cross platform-
Windows, Mac, Linux. I’m going to run it as a background process and
wondered whether there is a way to trap an OS signal that the host is
shutting down, allowing Ruby to tidy some things up first.

From what I gather the signal events between OSes are different, so I
fully expect to have to code conditionally, but any advice or pointers
would be greatly received, I’ve reached the point of Google blindness.
(:

Thx

John

trap an OS signal that the host is shutting down, allowing Ruby to tidy >some
things up first.

For unix-like OS’s, when the computer is shutting down all processes are
sent a SIGTERM, so if you use the the trap method (defined in the Kernel
module) like this,

trap(“TERM”) do
…important stuff…

end

it should work. For other OS’s, just find out what signals are sent on
shutdown, and see if they match the signals recognized by your Ruby
version by matching them against the output of Signal.list().

Hope this helps,

-Luke

On 10/14/2011 09:55, luke gruber wrote:

end
FYI, trapping TERM is not a guaranteed check that the host is shutting
down. It’s just a signal sent to programs to kill them that happens to
also be used by the usual shutdown process.

it should work. For other OS’s, just find out what signals are sent on
shutdown, and see if they match the signals recognized by your Ruby
version by matching them against the output of Signal.list().

Windows doesn’t use signals in the same sense as Unix. It sends
messages which are sort of the same, but you have to use an entirely
different mechanism to trap them. You’ll need to get chummy with some
gems for Windows or the Win32API module or equivalent for Ruby 1.9.

Does it make a difference for your program to clean up only on system
shutdown as opposed to program exit time (whenever that happens)? If
you just want to do the cleanup chore any time the program exits
(including system shutdown), you might simply be able to use the at_exit
method:

at_exit { puts “I’m dying!” }
puts “I’m alive!”
sleep 10

That should print “I’m alive!”, wait for 10 seconds, and then print “I’m
dying!”. If you instead hit Ctrl-C or send a TERM signal to the program
before the 10 seconds is up, it will still print “I’m dying”. The last
message won’t be printed if the KILL signal is sent however.

I haven’t tried to see if this would work during a Windows shutdown
event, but it should work on most Unix systems. If it doesn’t work on
Windows or if you really must know that it’s a system shutdown event
specifically, you may need to resort to triggering your cleanup logic to
run at shutdown as a separate program. This looks like a way to do that
in Windows:

http://www.computing.net/answers/windows-xp/run-program-on-shutdown/6762.html

I think you would configure launchd on OSX to do something similar. For
Linux systems it will depend on the init system being used for the
distribution in question.

-Jeremy

On Mon, Oct 17, 2011 at 4:10 PM, John H. [email protected]
wrote:

I feel brave I shall look into the modules as recommended, unless
someone else has anything to offer first?

Check out the win32-service gem from http://win32utils.rubyforge.org/
It allows you to create a Daemon (well, Service) for Windows.

If the gem doesn’t work for you, it should at least provide you a
pointer as to which messages Windows sends (there’s more-or-less two
kinds: Service control messages, and the WM_ENDSESSION message which
precedes a shutdown/logoff), and how to respond to them in your code.

Note: I have 0 experience with this gem or the win32utils.


Phillip G.

gplus.to/phgaw | twitter.com/phgaw

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibniz

Thanks guys. In the end I opted for Jeremy’s solution for it’s elegance.

I can confirm it works fine on both Linux and MacOSX (and handles both
interruptions and session terminations).

Unfortunately they don’t work with Windows. I listed all the available
signals and created a trap for them all, but when I run the app in a
console and close the console it still won’t clean up after itself. When
I feel brave I shall look into the modules as recommended, unless
someone else has anything to offer first?

Thx

John