trap HUP not working

W

wmwilson01

I know I must be doing something dumb here, but I can't figure out
what, and I'm about to give up. I'm setting a trap("HUP") to call a
couple of functions (basically to re-read a config). The first time
running a "kill -HUP" on the process works fine, but the second time it
exits with a "hangup". If I modify the trap to look like:

trap("HUP") {
trap("HUP", "IGNORE")
fun1
fun2
}

It doesn't hangup, but only the first "kill -HUP" actually re-reads the
configuration.

This is ruby 1.8.1
Code follows:
<code>
require "yaml"
require "socket"
require "net/smtp"
require "file/tail"
require "getoptlong"

$config = {}
$reread = false
thishost = Socket.gethostname
tivenv = "/etc/Tivoli/setup_env.sh"
usetiv = false
daemon = false
logfile = nil
config_file = nil

opts = GetoptLong.new(
["--config-file", "-c", GetoptLong::REQUIRED_ARGUMENT],
["--daemon", "-d", GetoptLong::NO_ARGUMENT],
["--logfile", "-l", GetoptLong::REQUIRED_ARGUMENT]
)

logan_struct = Struct::new("LoganStruct",
:pattern, :tmout, :mailhost, :email, :post, :expire)


def daemonize()
fork and exit
Process.setsid
fork and exit
File.open("/dev/null", "r+") do |devnull|
$stdin.reopen(devnull)
$stdout.reopen(devnull)
$stderr.reopen(devnull)
end

Dir.chdir("/")
end

def source(file)
response_match = Regexp.new(/^([^=]*)=(.*)/)

`#{ENV['SHELL']} -c ". #{file}; set"`.each_line do |line|
if response_match.match(line)
k, v = line.gsub(/^([^=]*)=(.*)/, '\1 \2').split
ENV[k] = v
end
end
end

def parseYamlConfig(file)
if File.exists?(file) and File.stat(file).readable?
$config = YAML::load(File.open(file))
else
raise "Unusable file #{file}"
end

$config
end

def setDefaultConfigVals(tmout = 3600)
$config["patterns"].each do |pat|
pat.expire = 0

case pat.pattern
when String
pat.pattern = Regexp.new(pat.pattern)
end

if not pat.mailhost
if $config["mailhost"]
pat.mailhost = $config["mailhost"]
end
end

if not pat.tmout
if $config["tmout"]
pat.tmout = $config["tmout"]
else
pat.tmout = tmout
end
end
end
end

def lookForPatternsInLogfile(file)
if File.exists?(file) and File.stat(file).readable?
File::Tail::Logfile.open(file, :rewind=>0) do |log|
log.tail do |line|
$config["patterns"].each do |pat|
if pat.pattern.match(line)
yield pat, line
end
end
end
end
end
end

def sendMail(email, alert, host, mailhost = "mailhost")
message = <<EndOfMsg
Subject: Log Analyzer Alert for #{host}
To: #{email}
From: LOGAN

The following pattern match was made on #{host} at #{Time.now}
#{alert}

EndOfMsg

Net::SMTP.start(mailhost, 25) do |smtp|
smtp.send_mail(message, '"LOGAN"', email)
end
end

def postMessage(msg)
system("postemsg #{msg} > /dev/null 2>&1")
end


opts.each do |opt, arg|
case opt
when "--daemon"
daemon = true
when "--logfile"
logfile = File.expand_path(arg)
when "--config-file"
config_file = File.expand_path(arg)
end
end

if not logfile or not config_file
fail "Usage: #$0 [-d] -c config_file -l logfile"
end

trap("HUP") do
trap("HUP", "IGNORE")
parseYamlConfig(config_file) or fail $!
setDefaultConfigVals
end

parseYamlConfig(config_file) or fail $!
setDefaultConfigVals
daemonize if daemon

if File.exists?(tivenv)
source(tivenv)
usetiv = true
end

lookForPatternsInLogfile(logfile) do |pat, msg|
if pat.expire <= Time.now.to_i
pat.expire = 0
end

if pat.expire == 0
pat.expire = Time.now.to_i + pat.tmout
if pat.email
sendMail(pat.email, msg, thishost, pat.mailhost)
end

if pat.post
postMessage(pat.post) if usetiv
end
end
end
</code>
 
A

Ara.T.Howard

On Thu, 2 Jun 2005 (e-mail address removed) wrote:

untested, but i think you may have to do something like
I know I must be doing something dumb here, but I can't figure out
what, and I'm about to give up. I'm setting a trap("HUP") to call a
couple of functions (basically to re-read a config). The first time
running a "kill -HUP" on the process works fine, but the second time it
exits with a "hangup". If I modify the trap to look like:

trap("HUP") {
trap("HUP", "IGNORE")
fun1
fun2
}

It doesn't hangup, but only the first "kill -HUP" actually re-reads the
configuration.

maybe something like

harp:~ > cat a.rb

hup_proc = lambda {|*a|
p 42
trap 'HUP', hup_proc
}

trap 'HUP', hup_proc

3.times{ Process::kill 'HUP', $$ }

harp:~ > ruby a.rb
42
42
42

hth.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| My religion is very simple. My religion is kindness.
| --Tenzin Gyatso
===============================================================================
 
R

Robert Klemme

I know I must be doing something dumb here, but I can't figure out
what, and I'm about to give up. I'm setting a trap("HUP") to call a
couple of functions (basically to re-read a config). The first time
running a "kill -HUP" on the process works fine, but the second time
it exits with a "hangup". If I modify the trap to look like:

trap("HUP") {
trap("HUP", "IGNORE")
fun1
fun2
}

It doesn't hangup, but only the first "kill -HUP" actually re-reads
the configuration.

You surprise me: you are really surprised that only the first signal is
processed? I mean, you set the signal handler to IGNORE on first run and
apparently you never reset it.

As far as I can see signal handlers are never executed concurrently but if
you want to be sure, I'd use standard thread synchronization:

require 'thread'

$HUP_LOCK = Mutex.new

trap "HUP" do
$HUP_LOCK.synchronize do
puts "your code here (queued up)"
end

if $HUP_LOCK.try_lock
puts "your code here (ingore duplicate invocations)"
$HUP_LOCK.unlock
end
end


Kind regards

robert
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top