Module: RRRSpec::Server

Defined in:
lib/rrrspec/server/cli.rb,
lib/rrrspec/server/arbiter.rb,
lib/rrrspec/server/version.rb,
lib/rrrspec/server/persister.rb,
lib/rrrspec/server/daemonizer.rb,
lib/rrrspec/server/dispatcher.rb,
lib/rrrspec/server/configuration.rb,
lib/rrrspec/server/worker_runner.rb,
lib/rrrspec/server/json_constructor.rb,
lib/rrrspec/server/persistent_models.rb,
lib/rrrspec/server/log_file_persister.rb,
lib/rrrspec/server/statistics_updater.rb

Defined Under Namespace

Modules: Arbiter, JSONConstructor, LogFilePersister, Persistence, Persister, StatisticsUpdater Classes: CLI, Dispatcher, ServerConfiguration, WorkerConfiguration, WorkerRunner

Constant Summary collapse

VERSION =
"0.4.3"
RESPAWN_INTERVAL_LIMIT_SEC =
30

Class Method Summary collapse

Class Method Details

.check_pidfile(pidfile) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/rrrspec/server/daemonizer.rb', line 36

def self.check_pidfile(pidfile)
  if File.exist?(pidfile)
    if File.readable?(pidfile)
      pid = File.read(pidfile).to_i
      begin
        Process.kill(0, pid)
        raise "Pid(#{pid}) is running"
      rescue Errno::EPERM
        raise "Pid(#{pid}) is running"
      rescue Errno::ESRCH
      end
    else
      raise "Cannot access #{pidfile}"
    end

    unless File.writable?(pidfile)
      raise "Cannot access #{pidfile}"
    end
  else
    unless File.writable?(File.dirname(pidfile))
      raise "Cannot access #{pidfile}"
    end
  end
end

.daemonizer(process_name, &block) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rrrspec/server/daemonizer.rb', line 5

def self.daemonizer(process_name, &block)
  $0 = process_name
  return block.call unless should_daemonize?

  pidfile = File.absolute_path(RRRSpec.configuration.pidfile || File.join("/var/run", "#{process_name}.pid"))
  check_pidfile(pidfile)

  if stdout_path = RRRSpec.configuration.stdout_path
    $stdout.reopen(stdout_path, 'a')
  end
  if stderr_path = RRRSpec.configuration.stderr_path
    $stderr.reopen(stderr_path, 'a')
  end
  Process.daemon(false, true)
  File.write(pidfile, Process.pid.to_s)
  setup_signal_handlers
  setup_atexit_handlers(pidfile)
  monitor_fork do
    Process::Sys.setuid(RRRSpec.configuration.user) if RRRSpec.configuration.user
    block.call
  end
end

.monitor_fork(&block) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/rrrspec/server/daemonizer.rb', line 80

def self.monitor_fork(&block)
  loop do
    started_at = Time.now
    pid = Process.fork(&block)
    Process.waitpid(pid)
    break unless should_monitor?
    if Time.now - started_at < RESPAWN_INTERVAL_LIMIT_SEC
      sleep RESPAWN_INTERVAL_LIMIT_SEC
    end
  end
end

.setup_atexit_handlers(pidfile) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/rrrspec/server/daemonizer.rb', line 69

def self.setup_atexit_handlers(pidfile)
  # Delete pid at exit
  current_pid = Process.pid
  at_exit do
    # Since at_exit handlers are inherited by child processes, it is the
    # case that the handlers are invoked in the child processes. This guard
    # is needed to avoid this.
    File.delete(pidfile) if Process.pid == current_pid
  end
end

.setup_signal_handlersObject



61
62
63
64
65
66
67
# File 'lib/rrrspec/server/daemonizer.rb', line 61

def self.setup_signal_handlers
  # Propagate the TERM signal to the children
  Signal.trap('TERM') do
    Signal.trap('TERM', 'DEFAULT')
    Process.kill('TERM', 0)
  end
end

.should_daemonize?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/rrrspec/server/daemonizer.rb', line 28

def self.should_daemonize?
  RRRSpec.configuration.daemonize == nil || RRRSpec.configuration.daemonize
end

.should_monitor?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/rrrspec/server/daemonizer.rb', line 32

def self.should_monitor?
  RRRSpec.configuration.monitor == nil || RRRSpec.configuration.monitor
end