Call a given block as a daemon
# File lib/daemons/daemonize.rb, line 39 39: def call_as_daemon(block, logfile_name = nil, app_name = nil) 40: # we use a pipe to return the PID of the daemon 41: rd, wr = IO.pipe 42: 43: if tmppid = safefork 44: # in the parent 45: 46: wr.close 47: pid = rd.read.to_i 48: rd.close 49: 50: Process.waitpid(tmppid) 51: 52: return pid 53: else 54: # in the child 55: 56: rd.close 57: 58: # Detach from the controlling terminal 59: unless sess_id = Process.setsid 60: raise Daemons.RuntimeException.new('cannot detach from controlling terminal') 61: end 62: 63: # Prevent the possibility of acquiring a controlling terminal 64: trap 'SIGHUP', 'IGNORE' 65: exit if pid = safefork 66: 67: wr.write Process.pid 68: wr.close 69: 70: $0 = app_name if app_name 71: 72: # Release old working directory 73: Dir.chdir "/" 74: 75: close_io() 76: 77: redirect_io(logfile_name) 78: 79: block.call 80: 81: exit 82: end 83: end
# File lib/daemons/daemonize.rb, line 118 118: def close_io() 119: # Make sure all input/output streams are closed 120: # Part I: close all IO objects (except for STDIN/STDOUT/STDERR) 121: ObjectSpace.each_object(IO) do |io| 122: unless [STDIN, STDOUT, STDERR].include?(io) 123: begin 124: unless io.closed? 125: io.close 126: end 127: rescue ::Exception 128: end 129: end 130: end 131: 132: # Make sure all input/output streams are closed 133: # Part II: close all file decriptors (except for STDIN/STDOUT/STDERR) 134: ios = Array.new(8192) {|i| IO.for_fd(i) rescue nil}.compact 135: ios.each do |io| 136: next if io.fileno < 3 137: io.close 138: end 139: end
Transform the current process into a daemon
# File lib/daemons/daemonize.rb, line 88 88: def daemonize(logfile_name = nil, app_name = nil) 89: # Split rand streams between spawning and daemonized process 90: srand 91: 92: # Fork and exit from the parent 93: safefork and exit 94: 95: # Detach from the controlling terminal 96: unless sess_id = Process.setsid 97: raise Daemons.RuntimeException.new('cannot detach from controlling terminal') 98: end 99: 100: # Prevent the possibility of acquiring a controlling terminal 101: trap 'SIGHUP', 'IGNORE' 102: exit if pid = safefork 103: 104: $0 = app_name if app_name 105: 106: # Release old working directory 107: Dir.chdir "/" 108: 109: close_io() 110: 111: redirect_io(logfile_name) 112: 113: return sess_id 114: end
Free STDIN/STDOUT/STDERR file descriptors and point them somewhere sensible
# File lib/daemons/daemonize.rb, line 145 145: def redirect_io(logfile_name) 146: begin; STDIN.reopen "/dev/null"; rescue ::Exception; end 147: 148: if logfile_name 149: begin 150: STDOUT.reopen logfile_name, "a" 151: File.chmod(0644, logfile_name) 152: STDOUT.sync = true 153: rescue ::Exception 154: begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end 155: end 156: else 157: begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end 158: end 159: 160: begin; STDERR.reopen STDOUT; rescue ::Exception; end 161: STDERR.sync = true 162: end
Try to fork if at all possible retrying every 5 sec if the maximum process limit for the system has been reached
# File lib/daemons/daemonize.rb, line 5 5: def safefork 6: tryagain = true 7: 8: while tryagain 9: tryagain = false 10: begin 11: if pid = fork 12: return pid 13: end 14: rescue Errno::EWOULDBLOCK 15: sleep 5 16: tryagain = true 17: end 18: end 19: end
Simulate the daemonization process (:ontop mode) NOTE: STDOUT and STDERR will not be redirected to the logfile, because in :ontop mode, we normally want to see the output
# File lib/daemons/daemonize.rb, line 26 26: def simulate(logfile_name = nil) 27: # Release old working directory 28: Dir.chdir "/" 29: 30: close_io() 31: 32: # Free STDIN and point them somewhere sensible 33: begin; STDIN.reopen "/dev/null"; rescue ::Exception; end 34: end
Call a given block as a daemon
# File lib/daemons/daemonize.rb, line 39 39: def call_as_daemon(block, logfile_name = nil, app_name = nil) 40: # we use a pipe to return the PID of the daemon 41: rd, wr = IO.pipe 42: 43: if tmppid = safefork 44: # in the parent 45: 46: wr.close 47: pid = rd.read.to_i 48: rd.close 49: 50: Process.waitpid(tmppid) 51: 52: return pid 53: else 54: # in the child 55: 56: rd.close 57: 58: # Detach from the controlling terminal 59: unless sess_id = Process.setsid 60: raise Daemons.RuntimeException.new('cannot detach from controlling terminal') 61: end 62: 63: # Prevent the possibility of acquiring a controlling terminal 64: trap 'SIGHUP', 'IGNORE' 65: exit if pid = safefork 66: 67: wr.write Process.pid 68: wr.close 69: 70: $0 = app_name if app_name 71: 72: # Release old working directory 73: Dir.chdir "/" 74: 75: close_io() 76: 77: redirect_io(logfile_name) 78: 79: block.call 80: 81: exit 82: end 83: end
# File lib/daemons/daemonize.rb, line 118 118: def close_io() 119: # Make sure all input/output streams are closed 120: # Part I: close all IO objects (except for STDIN/STDOUT/STDERR) 121: ObjectSpace.each_object(IO) do |io| 122: unless [STDIN, STDOUT, STDERR].include?(io) 123: begin 124: unless io.closed? 125: io.close 126: end 127: rescue ::Exception 128: end 129: end 130: end 131: 132: # Make sure all input/output streams are closed 133: # Part II: close all file decriptors (except for STDIN/STDOUT/STDERR) 134: ios = Array.new(8192) {|i| IO.for_fd(i) rescue nil}.compact 135: ios.each do |io| 136: next if io.fileno < 3 137: io.close 138: end 139: end
Transform the current process into a daemon
# File lib/daemons/daemonize.rb, line 88 88: def daemonize(logfile_name = nil, app_name = nil) 89: # Split rand streams between spawning and daemonized process 90: srand 91: 92: # Fork and exit from the parent 93: safefork and exit 94: 95: # Detach from the controlling terminal 96: unless sess_id = Process.setsid 97: raise Daemons.RuntimeException.new('cannot detach from controlling terminal') 98: end 99: 100: # Prevent the possibility of acquiring a controlling terminal 101: trap 'SIGHUP', 'IGNORE' 102: exit if pid = safefork 103: 104: $0 = app_name if app_name 105: 106: # Release old working directory 107: Dir.chdir "/" 108: 109: close_io() 110: 111: redirect_io(logfile_name) 112: 113: return sess_id 114: end
Free STDIN/STDOUT/STDERR file descriptors and point them somewhere sensible
# File lib/daemons/daemonize.rb, line 145 145: def redirect_io(logfile_name) 146: begin; STDIN.reopen "/dev/null"; rescue ::Exception; end 147: 148: if logfile_name 149: begin 150: STDOUT.reopen logfile_name, "a" 151: File.chmod(0644, logfile_name) 152: STDOUT.sync = true 153: rescue ::Exception 154: begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end 155: end 156: else 157: begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end 158: end 159: 160: begin; STDERR.reopen STDOUT; rescue ::Exception; end 161: STDERR.sync = true 162: end
Try to fork if at all possible retrying every 5 sec if the maximum process limit for the system has been reached
# File lib/daemons/daemonize.rb, line 5 5: def safefork 6: tryagain = true 7: 8: while tryagain 9: tryagain = false 10: begin 11: if pid = fork 12: return pid 13: end 14: rescue Errno::EWOULDBLOCK 15: sleep 5 16: tryagain = true 17: end 18: end 19: end
Simulate the daemonization process (:ontop mode) NOTE: STDOUT and STDERR will not be redirected to the logfile, because in :ontop mode, we normally want to see the output
# File lib/daemons/daemonize.rb, line 26 26: def simulate(logfile_name = nil) 27: # Release old working directory 28: Dir.chdir "/" 29: 30: close_io() 31: 32: # Free STDIN and point them somewhere sensible 33: begin; STDIN.reopen "/dev/null"; rescue ::Exception; end 34: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.