boreman 0.1.27 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6335a3b3a005c92b43305c6a9a185597cb623ed
4
- data.tar.gz: dc5ba754a8387c82cc795b5afdd71f091ab5440d
3
+ metadata.gz: b43032f6ccbd8241a33a650f841b0918cb1d33d4
4
+ data.tar.gz: 8b7fde40f727ed9f62e6fc1eec3edc9ba99f75cd
5
5
  SHA512:
6
- metadata.gz: 280a78fd78cac5f2cd49a0e188154981618bc1b60e4b5dfc6ae5834cacc1f5a585f0d5b3f99be26c9d611d1bc794a3f23b470c7f2b1be665301e246f6e566f63
7
- data.tar.gz: 951312a6f3b690d94969211b0af5a36c05b661ddd9ef647dfaa0a0750c7755d8eb35e1cc66663ead9157079c9225f0079eb06ec5d68829755928ad4aea2c7108
6
+ metadata.gz: a92f68270e25b7f0449c95aac5089b7f75d2298ce094385736d4253fe7547e7aaf962f41002e1e0bc98cb398294dcaf9017d820bfa6ddcfdcf9f73ad9d2cdda3
7
+ data.tar.gz: 61f18ed3c883abd891780d6bd2dbaf6c2b83ac7a17ad2c22066dd130fba7fe0cf399e976e66043bfc0a67804780bc087cd9281c7c4bdae038824d50cebbeed35
@@ -1,4 +1,5 @@
1
1
  require "boreman/version"
2
+ require "boreman/daemonize"
2
3
 
3
4
  module Boreman
4
5
  def self.run(action, selector, opts = {})
@@ -93,32 +94,13 @@ module Boreman
93
94
  if cmd = procs[selector]
94
95
  cmd = prepare_command(cmd)
95
96
 
96
- begin
97
- r, w = IO.pipe
98
-
99
- fpid = fork do
100
- STDOUT.reopen(w)
101
-
102
- r.close
103
-
104
- pid = Process.spawn cmd, pgroup: true
105
-
106
- puts pid.to_s
107
-
108
- exit! 0
109
- end
110
-
111
- pid = r.gets.chomp.to_i
112
-
113
- Process.detach(fpid)
114
- Process.detach(pid)
115
-
116
- write_pid selector, pid
117
- puts "Started #{selector}, pid = #{pid}"
118
- ensure
119
- r.close rescue nil
120
- w.close rescue nil
97
+ run = Proc.new do
98
+ Kernel.exec cmd
121
99
  end
100
+
101
+ pid = Daemonize.call_as_daemon run
102
+ write_pid selector, pid
103
+ puts "Started #{selector}, pid = #{pid}"
122
104
  else
123
105
  puts "Entry #{selector} not found in Procfile"
124
106
  end
@@ -0,0 +1,141 @@
1
+ module Daemonize
2
+ # Try to fork if at all possible retrying every 5 sec if the
3
+ # maximum process limit for the system has been reached
4
+ def self.safefork
5
+ tryagain = true
6
+
7
+ while tryagain
8
+ tryagain = false
9
+ begin
10
+ if pid = fork
11
+ return pid
12
+ end
13
+ rescue Errno::EWOULDBLOCK
14
+ sleep 5
15
+ tryagain = true
16
+ end
17
+ end
18
+ end
19
+
20
+ # Call a given block as a daemon
21
+ def self.call_as_daemon(block, logfile_name = nil, app_name = nil)
22
+ # we use a pipe to return the PID of the daemon
23
+ rd, wr = IO.pipe
24
+
25
+ if tmppid = safefork
26
+ # in the parent
27
+
28
+ wr.close
29
+ pid = rd.read.to_i
30
+ rd.close
31
+
32
+ Process.waitpid(tmppid)
33
+
34
+ return pid
35
+ else
36
+ # in the child
37
+
38
+ rd.close
39
+
40
+ # Detach from the controlling terminal
41
+ unless Process.setsid
42
+ fail Daemons.RuntimeException.new('cannot detach from controlling terminal')
43
+ end
44
+
45
+ # Prevent the possibility of acquiring a controlling terminal
46
+ trap 'SIGHUP', 'IGNORE'
47
+ exit if pid = safefork
48
+
49
+ wr.write Process.pid
50
+ wr.close
51
+
52
+ $0 = app_name if app_name
53
+
54
+ close_io
55
+
56
+ redirect_io(logfile_name)
57
+
58
+ # Split rand streams between spawning and daemonized process
59
+ srand
60
+
61
+ block.call
62
+
63
+ exit
64
+ end
65
+ end
66
+
67
+ # Transform the current process into a daemon
68
+ def self.daemonize(logfile_name = nil, app_name = nil)
69
+ # Fork and exit from the parent
70
+ safefork && exit
71
+
72
+ # Detach from the controlling terminal
73
+ unless sess_id = Process.setsid
74
+ fail Daemons.RuntimeException.new('cannot detach from controlling terminal')
75
+ end
76
+
77
+ # Prevent the possibility of acquiring a controlling terminal
78
+ trap 'SIGHUP', 'IGNORE'
79
+ exit if safefork
80
+
81
+ $0 = app_name if app_name
82
+
83
+ # Release old working directory
84
+ Dir.chdir '/'
85
+
86
+ close_io
87
+
88
+ redirect_io(logfile_name)
89
+
90
+ # Split rand streams between spawning and daemonized process
91
+ srand
92
+
93
+ sess_id
94
+ end
95
+
96
+ def self.close_io
97
+ # Make sure all input/output streams are closed
98
+ # Part I: close all IO objects (except for $stdin/$stdout/$stderr)
99
+ ObjectSpace.each_object(IO) do |io|
100
+ unless [$stdin, $stdout, $stderr].include?(io)
101
+ io.close rescue nil
102
+ end
103
+ end
104
+
105
+ # Make sure all input/output streams are closed
106
+ # Part II: close all file decriptors (except for $stdin/$stdout/$stderr)
107
+ 3.upto(8192) do |i|
108
+ IO.for_fd(i).close rescue nil
109
+ end
110
+ end
111
+
112
+ # Free $stdin/$stdout/$stderr file descriptors and
113
+ # point them somewhere sensible
114
+ def self.redirect_io(logfile_name)
115
+ begin; $stdin.reopen '/dev/null'; rescue ::Exception; end
116
+
117
+ if logfile_name == 'SYSLOG'
118
+ # attempt to use syslog via syslogio
119
+ begin
120
+ require 'syslogio'
121
+ $stdout = ::Daemons::SyslogIO.new($0, :local0, :info, $stdout)
122
+ $stderr = ::Daemons::SyslogIO.new($0, :local0, :err, $stderr)
123
+ # error out early so we can fallback to null
124
+ $stdout.puts "no logfile provided, output redirected to syslog"
125
+ rescue ::Exception
126
+ # on unsupported platforms simply reopen /dev/null
127
+ begin; $stdout.reopen '/dev/null'; rescue ::Exception; end
128
+ begin; $stderr.reopen '/dev/null'; rescue ::Exception; end
129
+ end
130
+ elsif logfile_name
131
+ $stdout.reopen logfile_name, 'a'
132
+ File.chmod(0644, logfile_name)
133
+ $stdout.sync = true
134
+ begin; $stderr.reopen $stdout; rescue ::Exception; end
135
+ $stderr.sync = true
136
+ else
137
+ begin; $stdout.reopen '/dev/null'; rescue ::Exception; end
138
+ begin; $stderr.reopen '/dev/null'; rescue ::Exception; end
139
+ end
140
+ end
141
+ end
@@ -1,3 +1,3 @@
1
1
  module Boreman
2
- VERSION = "0.1.27"
2
+ VERSION = "0.1.28"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boreman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.27
4
+ version: 0.1.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Brett
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-25 00:00:00.000000000 Z
11
+ date: 2017-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,6 +58,7 @@ files:
58
58
  - boreman.gemspec
59
59
  - exe/boreman
60
60
  - lib/boreman.rb
61
+ - lib/boreman/daemonize.rb
61
62
  - lib/boreman/version.rb
62
63
  homepage:
63
64
  licenses: []