1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#!/usr/bin/env ruby -w
# encoding: UTF-8
#
# = Daemon.rb -- The TaskJuggler III Project Management Software
#
# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
# by Chris Schlaeger <cs@taskjuggler.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
require 'taskjuggler/MessageHandler'
class TaskJuggler
# This class provides the basic functionality to turn the current process
# into a background process (daemon). To use it, derive you main class from
# this class and call the start() method.
class Daemon
include MessageHandler
attr_accessor :pidFile, :daemonize
def initialize
# You can set this flag to false to prevent the program from
# disconnecting from the current terminal. This is useful for debugging
# purposes.
@daemonize = true
# Save the PID of the running daemon as number into this file.
@pidFile = nil
end
# Call this method to turn the process into a background process.
def start
return 0 unless @daemonize
# Fork and have the parent exit
if (pid = fork) == -1
fatal('first_fork_failed', 'First fork failed')
elsif !pid.nil?
# This is the parent. We can exit now.
debug('', "Forked a child process with PID #{pid}")
exit! 0
end
# Create a new session
Process.setsid
# Fork again to make sure we lose the controlling terminal
if (pid = fork) == -1
fatal('second_fork_failed', 'Second fork failed')
elsif !pid.nil?
# This is the parent. We can exit now.
debug('', "Forked a child process with PID #{pid}")
exit! 0
end
@pid = Process.pid
writePidFile
# Change current working directory to the file system root
Dir.chdir '/'
# Make sure we can create files with any permission
File.umask 0
# We no longer have a controlling terminal, so these are useless.
$stdin.reopen('/dev/null')
$stdout.reopen('/dev/null', 'a')
$stderr.reopen($stdout)
info('daemon_pid',
"The process is running as daemon now with PID #{@pid}")
0
end
# This method may provide some cleanup functionality in the future. You
# better call it before you exit.
def stop
if @pidFile
begin
File.delete(@pidFile)
rescue
warning('cannot_delete_pidfile',
"Cannote delete the PID file (#{@pidFile}): #{$!}")
end
info('daemon_deleted_pidfile', "PID file #{@pidFile} deleted")
end
end
private
def writePidFile
if @pidFile
# Prepend the current working dir to @pidFile unless it's already an
# absolute path. The working dir is changed to '/' later. We need the
# absolute name to be able to delete it on exit again.
if @pidFile[0] != '/'
@pidFile = File.join(Dir.getwd, @pidFile)
end
# If requested, write the PID of the daemon to the specified file.
begin
File.open(@pidFile, 'w') do |f|
f.puts @pid
end
rescue
warning('cannot_save_pidfile', "Cannot write PID to #{@pidFile}")
end
info('daemon_wrote_pidfile',
"PID file #{@pidFile} written with PID #{@pid}")
end
end
end
end
|