Module: Emissary::ServerController

Included in:
Daemon
Defined in:
lib/emissary/daemon.rb

Overview

Some of the ServerController/Daemon stuff has been borrowed from Servolux::Daemon and Servolux::Server, so: Thanks to Tim Pease for those parts that are gleaned from Servolux

Constant Summary collapse

SIGNALS =
%w[HUP INT TERM USR1 USR2 EXIT] & Signal.list.keys
DEFAULT_PID_FILE_MODE =
0640

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#pid_fileObject



99
100
101
# File 'lib/emissary/daemon.rb', line 99

def pid_file
  @pid_file ||= File.join(config[:general][:pid_dir], (config[:general][:pid_file] || 'emissary.pid'))
end

#pid_file_modeObject

Returns the value of attribute pid_file_mode.



32
33
34
# File 'lib/emissary/daemon.rb', line 32

def pid_file_mode
  @pid_file_mode
end

Instance Method Details

#alive?Boolean

Returns true if the daemon process is currently running. Returns false if this is not the case. The status of the process is determined by sending a signal to the process identified by the pid_file.

Returns:

  • (Boolean)


41
42
43
44
45
46
47
48
49
50
51
# File 'lib/emissary/daemon.rb', line 41

def alive?
  pid = retrieve_pid
  Process.kill(0, pid)
  true
rescue Errno::ESRCH, Errno::ENOENT
  false
rescue Errno::EACCES => err
  logger.error "You do not have access to the PID file at " \
               "#{pid_file.inspect}: #{err.message}"
  false
end

#create_pid_fileObject



107
108
109
110
# File 'lib/emissary/daemon.rb', line 107

def create_pid_file
  logger.debug "Server #{name.inspect} creating pid file #{pid_file.inspect}"
  File.open(pid_file, 'w', pid_file_mode) {|fd| fd.write(Process.pid.to_s)}
end

#delete_pid_fileObject



112
113
114
115
116
117
118
119
120
# File 'lib/emissary/daemon.rb', line 112

def delete_pid_file
  if test(?f, pid_file)
    pid = Integer(File.read(pid_file).strip)
    return unless pid == Process.pid
  
    logger.debug "Server #{name.inspect} removing pid file #{pid_file.inspect}"
    File.delete(pid_file)
  end
end

#kill(signal = 'INT') ⇒ Daemon

Send a signal to the daemon process identified by the PID file. The default signal to send is ‘INT’ (2). The signal can be given either as a string or a signal number.

process

Parameters:

  • signal (String, Integer) (defaults to: 'INT')

    The kill signal to send to the daemon

Returns:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/emissary/daemon.rb', line 69

def kill( signal = 'INT' )
  signal = Signal.list.invert[signal] if signal.is_a?(Integer)
  pid = retrieve_pid
  logger.info "Killing PID #{pid} with #{signal}"
  Process.kill(signal, pid)
  self
rescue Errno::EINVAL
  logger.error "Failed to kill PID #{pid} with #{signal}: " \
               "'#{signal}' is an invalid or unsupported signal number."
rescue Errno::EPERM
  logger.error "Failed to kill PID #{pid} with #{signal}: " \
               "Insufficient permissions."
rescue Errno::ESRCH
  logger.error "Failed to kill PID #{pid} with #{signal}: " \
               "Process is deceased or zombie."
rescue Errno::EACCES => err
  logger.error err.message
rescue Errno::ENOENT => err
  logger.error "Could not find a PID file at #{pid_file.inspect}. " \
               "Most likely the process is no longer running."
rescue Exception => err
  unless err.is_a?(SystemExit)
    logger.error "Failed to kill PID #{pid} with #{signal}: #{err.message}"
  end
end

#pidObject



95
96
97
# File 'lib/emissary/daemon.rb', line 95

def pid
  alive? ? retrieve_pid : nil
end

#pid_dirObject



103
104
105
# File 'lib/emissary/daemon.rb', line 103

def pid_dir
  @pid_dir ||= File.join(config[:general][:pid_dir])
end

#retrieve_pidObject



53
54
55
56
57
58
59
# File 'lib/emissary/daemon.rb', line 53

def retrieve_pid
  Integer(File.read(pid_file).strip)
rescue TypeError
  raise Error, "A PID file was not specified."
rescue ArgumentError
  raise Error, "#{pid_file.inspect} does not contain a valid PID."
end

#trap_signalsObject



122
123
124
125
126
127
# File 'lib/emissary/daemon.rb', line 122

def trap_signals
  SIGNALS.each do |sig|
    m = sig.downcase.to_sym
    Signal.trap(sig) { self.send(m) rescue nil } if self.respond_to? m
  end
end