zeus 0.2.4 → 0.2.5
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.
- data/ext/fsevents-wrapper/fsevents-wrapper +0 -0
- data/ext/fsevents-wrapper/main.m +3 -5
- data/lib/zeus/server.rb +26 -61
- data/lib/zeus/server/acceptor.rb +3 -5
- data/lib/zeus/server/acceptor_registration_monitor.rb +18 -11
- data/lib/zeus/server/client_handler.rb +11 -8
- data/lib/zeus/server/file_monitor/fsevent.rb +5 -9
- data/lib/zeus/server/process_tree.rb +78 -0
- data/lib/zeus/server/process_tree_monitor.rb +47 -73
- data/lib/zeus/server/stage.rb +8 -4
- data/lib/zeus/version.rb +1 -1
- metadata +2 -1
Binary file
|
data/ext/fsevents-wrapper/main.m
CHANGED
@@ -123,11 +123,9 @@ void configureTimerAndRun()
|
|
123
123
|
|
124
124
|
int main(int argc, const char * argv[])
|
125
125
|
{
|
126
|
-
|
127
|
-
|
128
|
-
_fileIsWatched = [[NSMutableDictionary alloc] initWithCapacity:500];
|
126
|
+
_watchedFiles = CFArrayCreateMutable(NULL, 0, NULL);
|
127
|
+
_fileIsWatched = [[NSMutableDictionary alloc] initWithCapacity:500];
|
129
128
|
|
130
|
-
|
131
|
-
}
|
129
|
+
configureTimerAndRun();
|
132
130
|
return 0;
|
133
131
|
}
|
data/lib/zeus/server.rb
CHANGED
@@ -7,6 +7,7 @@ module Zeus
|
|
7
7
|
autoload :Stage, 'zeus/server/stage'
|
8
8
|
autoload :Acceptor, 'zeus/server/acceptor'
|
9
9
|
autoload :FileMonitor, 'zeus/server/file_monitor'
|
10
|
+
autoload :ProcessTree, 'zeus/server/process_tree'
|
10
11
|
autoload :ClientHandler, 'zeus/server/client_handler'
|
11
12
|
autoload :ProcessTreeMonitor, 'zeus/server/process_tree_monitor'
|
12
13
|
autoload :AcceptorRegistrationMonitor, 'zeus/server/acceptor_registration_monitor'
|
@@ -19,15 +20,13 @@ module Zeus
|
|
19
20
|
@@definition.acceptors
|
20
21
|
end
|
21
22
|
|
22
|
-
attr_reader :client_handler, :acceptor_registration_monitor
|
23
23
|
def initialize
|
24
24
|
@file_monitor = FileMonitor::FSEvent.new(&method(:dependency_did_change))
|
25
25
|
@acceptor_registration_monitor = AcceptorRegistrationMonitor.new
|
26
|
-
@process_tree_monitor = ProcessTreeMonitor.new
|
26
|
+
@process_tree_monitor = ProcessTreeMonitor.new(@file_monitor)
|
27
27
|
acceptor_commands = self.class.acceptors.map(&:commands).flatten
|
28
|
-
@client_handler = ClientHandler.new(acceptor_commands,
|
28
|
+
@client_handler = ClientHandler.new(acceptor_commands, self)
|
29
29
|
|
30
|
-
# TODO: deprecate Zeus::Server.define! maybe. We can do that better...
|
31
30
|
@plan = @@definition.to_domain_object(self)
|
32
31
|
end
|
33
32
|
|
@@ -35,85 +34,51 @@ module Zeus
|
|
35
34
|
@process_tree_monitor.kill_nodes_with_feature(file)
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
@w_msg.send(PID_TYPE + line, 0)
|
41
|
-
rescue Errno::ENOBUFS
|
42
|
-
sleep 0.2
|
43
|
-
retry
|
44
|
-
end
|
45
|
-
|
46
|
-
FEATURE_TYPE = "F"
|
47
|
-
def w_feature line
|
48
|
-
@w_msg.send(FEATURE_TYPE + line, 0)
|
49
|
-
rescue Errno::ENOBUFS
|
50
|
-
sleep 0.2
|
51
|
-
retry
|
37
|
+
def monitors
|
38
|
+
[@file_monitor, @process_tree_monitor, @acceptor_registration_monitor, @client_handler]
|
52
39
|
end
|
53
40
|
|
54
41
|
def run
|
55
42
|
$0 = "zeus master"
|
56
43
|
trap("INT") { exit 0 }
|
57
44
|
|
58
|
-
@
|
59
|
-
|
60
|
-
# boot the actual app
|
61
|
-
@plan.run
|
62
|
-
@w_msg.close
|
45
|
+
@plan.run(true) # boot the actual app
|
46
|
+
monitors.each(&:close_child_socket)
|
63
47
|
|
64
48
|
loop do
|
65
|
-
|
66
|
-
# TODO: Make @r_msg a Monitor instead. All that logic should be its own thing.
|
67
|
-
datasources = [@r_msg, *monitors.map(&:datasource)]
|
68
|
-
|
69
|
-
ready, _, _ = IO.select(datasources, [], [], 1)
|
49
|
+
ready, = IO.select(monitors.map(&:datasource), [], [], 1)
|
70
50
|
next unless ready
|
71
51
|
monitors.each do |m|
|
72
52
|
m.on_datasource_event if ready.include?(m.datasource)
|
73
53
|
end
|
74
|
-
handle_messages if ready.include?(@r_msg)
|
75
54
|
end
|
76
|
-
|
77
55
|
ensure
|
78
56
|
File.unlink(Zeus::SOCKET_NAME)
|
79
57
|
end
|
80
58
|
|
81
|
-
|
82
|
-
50.times {
|
83
|
-
handle_message
|
84
|
-
}
|
85
|
-
rescue Errno::EAGAIN
|
86
|
-
end
|
59
|
+
module ChildProcessApi
|
87
60
|
|
88
|
-
|
89
|
-
|
90
|
-
case data[0]
|
91
|
-
when FEATURE_TYPE
|
92
|
-
handle_feature_message(data[1..-1])
|
93
|
-
when PID_TYPE
|
94
|
-
handle_pid_message(data[1..-1])
|
95
|
-
else
|
96
|
-
raise "Unrecognized message"
|
61
|
+
def __CHILD__close_parent_sockets
|
62
|
+
monitors.each(&:close_parent_socket)
|
97
63
|
end
|
98
|
-
end
|
99
64
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
@process_tree_monitor.process_has_parent(pid, ppid)
|
104
|
-
end
|
65
|
+
def __CHILD__pid_has_ppid(pid, ppid)
|
66
|
+
@process_tree_monitor.__CHILD__send_pid("#{pid}:#{Process.ppid}")
|
67
|
+
end
|
105
68
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
@process_tree_monitor.process_has_feature(pid, file)
|
110
|
-
@file_monitor.watch(file)
|
111
|
-
end
|
69
|
+
def __CHILD__pid_has_feature(pid, feature)
|
70
|
+
@process_tree_monitor.__CHILD__send_feature("#{pid}:#{feature}")
|
71
|
+
end
|
112
72
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
73
|
+
def __CHILD__register_acceptor(io)
|
74
|
+
@acceptor_registration_monitor.__CHILD__register_acceptor(io)
|
75
|
+
end
|
76
|
+
|
77
|
+
def __CHILD__find_acceptor_for_command(command)
|
78
|
+
@acceptor_registration_monitor.__CHILD__find_acceptor_for_command(command)
|
79
|
+
end
|
80
|
+
|
81
|
+
end ; include ChildProcessApi
|
117
82
|
|
118
83
|
end
|
119
84
|
end
|
data/lib/zeus/server/acceptor.rb
CHANGED
@@ -9,8 +9,6 @@ module Zeus
|
|
9
9
|
attr_accessor :name, :aliases, :description, :action
|
10
10
|
def initialize(server)
|
11
11
|
@server = server
|
12
|
-
@client_handler = server.client_handler
|
13
|
-
@registration_monitor = server.acceptor_registration_monitor
|
14
12
|
end
|
15
13
|
|
16
14
|
def register_with_client_handler(pid)
|
@@ -18,7 +16,7 @@ module Zeus
|
|
18
16
|
|
19
17
|
@s_acceptor.puts registration_data(pid)
|
20
18
|
|
21
|
-
@
|
19
|
+
@server.__CHILD__register_acceptor(@s_client_handler)
|
22
20
|
end
|
23
21
|
|
24
22
|
def registration_data(pid)
|
@@ -58,7 +56,7 @@ module Zeus
|
|
58
56
|
|
59
57
|
register_with_client_handler(pid)
|
60
58
|
|
61
|
-
@server.
|
59
|
+
@server.__CHILD__pid_has_ppid(pid, Process.ppid)
|
62
60
|
|
63
61
|
Zeus.ui.as_zeus "starting acceptor `#{@name}`"
|
64
62
|
trap("INT") {
|
@@ -69,7 +67,7 @@ module Zeus
|
|
69
67
|
# Apparently threads don't continue in forks.
|
70
68
|
Thread.new {
|
71
69
|
$LOADED_FEATURES.each do |f|
|
72
|
-
@server.
|
70
|
+
@server.__CHILD__pid_has_feature(pid, f)
|
73
71
|
end
|
74
72
|
}
|
75
73
|
|
@@ -2,11 +2,13 @@ module Zeus
|
|
2
2
|
class Server
|
3
3
|
class AcceptorRegistrationMonitor
|
4
4
|
|
5
|
-
def datasource ; @
|
5
|
+
def datasource ; @sock ; end
|
6
6
|
def on_datasource_event ; handle_message ; end
|
7
|
+
def close_child_socket ; @__CHILD__sock.close ; end
|
8
|
+
def close_parent_socket ; @sock.close ; end
|
7
9
|
|
8
10
|
def initialize
|
9
|
-
@
|
11
|
+
@sock, @__CHILD__sock = UNIXSocket.pair
|
10
12
|
@acceptors = []
|
11
13
|
@pings = {}
|
12
14
|
end
|
@@ -14,7 +16,7 @@ module Zeus
|
|
14
16
|
AcceptorStub = Struct.new(:pid, :socket, :commands, :description)
|
15
17
|
|
16
18
|
def handle_message
|
17
|
-
io = @
|
19
|
+
io = @sock.recv_io
|
18
20
|
|
19
21
|
data = JSON.parse(io.readline.chomp)
|
20
22
|
type = data['type']
|
@@ -58,15 +60,20 @@ module Zeus
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
def find_acceptor_for_command(command)
|
62
|
-
@acceptors.detect { |acceptor|
|
63
|
-
acceptor.commands.include?(command)
|
64
|
-
}
|
65
|
-
end
|
66
63
|
|
67
|
-
|
68
|
-
|
69
|
-
|
64
|
+
module ChildProcessApi
|
65
|
+
|
66
|
+
def __CHILD__find_acceptor_for_command(command)
|
67
|
+
@acceptors.detect { |acceptor|
|
68
|
+
acceptor.commands.include?(command)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def __CHILD__register_acceptor(io)
|
73
|
+
@__CHILD__sock.send_io(io)
|
74
|
+
end
|
75
|
+
|
76
|
+
end ; include ChildProcessApi
|
70
77
|
|
71
78
|
end
|
72
79
|
|
@@ -24,21 +24,23 @@ module Zeus
|
|
24
24
|
# 4. ClientHandler forwards the pid to the client over S_CLI.
|
25
25
|
#
|
26
26
|
class ClientHandler
|
27
|
-
def datasource
|
27
|
+
def datasource ; @listener ; end
|
28
28
|
def on_datasource_event ; handle_server_connection ; end
|
29
|
+
def close_child_socket ; end
|
30
|
+
def close_parent_socket ; @listener.close ; end
|
29
31
|
|
30
|
-
def initialize(acceptor_commands,
|
31
|
-
@
|
32
|
+
def initialize(acceptor_commands, server)
|
33
|
+
@server = server
|
32
34
|
@acceptor_commands = acceptor_commands
|
33
|
-
@
|
34
|
-
@
|
35
|
+
@listener = UNIXServer.new(Zeus::SOCKET_NAME)
|
36
|
+
@listener.listen(10)
|
35
37
|
rescue Errno::EADDRINUSE
|
36
38
|
Zeus.ui.error "Zeus appears to be already running in this project. If not, remove .zeus.sock and try again."
|
37
39
|
exit 1
|
38
40
|
end
|
39
41
|
|
40
42
|
def handle_server_connection
|
41
|
-
s_client = @
|
43
|
+
s_client = @listener.accept
|
42
44
|
|
43
45
|
# 1
|
44
46
|
data = JSON.parse(s_client.readline.chomp)
|
@@ -76,7 +78,8 @@ module Zeus
|
|
76
78
|
regmsg = {type: 'wait', command: command}
|
77
79
|
|
78
80
|
s, r = UNIXSocket.pair
|
79
|
-
|
81
|
+
|
82
|
+
@server.__CHILD__register_acceptor(r)
|
80
83
|
s << "#{regmsg.to_json}\n"
|
81
84
|
|
82
85
|
s.readline # wait
|
@@ -99,7 +102,7 @@ module Zeus
|
|
99
102
|
s_client, client_terminal,
|
100
103
|
"no such command `#{command}`.")
|
101
104
|
end
|
102
|
-
acceptor = @
|
105
|
+
acceptor = @server.__CHILD__find_acceptor_for_command(command)
|
103
106
|
unless acceptor
|
104
107
|
wait_for_acceptor(
|
105
108
|
s_client, client_terminal, command,
|
@@ -6,8 +6,10 @@ module Zeus
|
|
6
6
|
class FSEvent
|
7
7
|
WRAPPER_PATH = File.expand_path("../../../../../ext/fsevents-wrapper/fsevents-wrapper", __FILE__)
|
8
8
|
|
9
|
-
def datasource
|
9
|
+
def datasource ; @io_out ; end
|
10
10
|
def on_datasource_event ; handle_changed_files ; end
|
11
|
+
def close_child_socket ; end
|
12
|
+
def close_parent_socket ; [@io_in, @io_out].each(&:close) ; end
|
11
13
|
|
12
14
|
def initialize(&change_callback)
|
13
15
|
@change_callback = change_callback
|
@@ -17,13 +19,8 @@ module Zeus
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def handle_changed_files
|
20
|
-
50.times {
|
21
|
-
|
22
|
-
read_and_notify_files
|
23
|
-
rescue Errno::EAGAIN
|
24
|
-
break
|
25
|
-
end
|
26
|
-
}
|
22
|
+
50.times { read_and_notify_files }
|
23
|
+
rescue Errno::EAGAIN
|
27
24
|
end
|
28
25
|
|
29
26
|
def read_and_notify_files
|
@@ -42,7 +39,6 @@ module Zeus
|
|
42
39
|
def watch(file)
|
43
40
|
return false if @watched_files[file]
|
44
41
|
@watched_files[file] = true
|
45
|
-
File.open('a.log', 'a') { |f| f.puts file }
|
46
42
|
@io_in.puts file
|
47
43
|
true
|
48
44
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Zeus
|
2
|
+
class Server
|
3
|
+
class ProcessTree
|
4
|
+
class Node
|
5
|
+
attr_accessor :pid, :children, :features
|
6
|
+
def initialize(pid)
|
7
|
+
@pid, @children, @features = pid, [], {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_child(node)
|
11
|
+
self.children << node
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_feature(feature)
|
15
|
+
self.features[feature] = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_feature?(feature)
|
19
|
+
self.features[feature] == true
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"(#{pid}:#{features.size}:[#{children.map(&:inspect).join(",")}])"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
@root.inspect
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@root = Node.new(Process.pid)
|
34
|
+
@nodes_by_pid = {Process.pid => @root}
|
35
|
+
end
|
36
|
+
|
37
|
+
def node_for_pid(pid)
|
38
|
+
@nodes_by_pid[pid.to_i] ||= Node.new(pid.to_i)
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_has_parent(pid, ppid)
|
42
|
+
curr = node_for_pid(pid)
|
43
|
+
base = node_for_pid(ppid)
|
44
|
+
base.add_child(curr)
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_has_feature(pid, feature)
|
48
|
+
node = node_for_pid(pid)
|
49
|
+
node.add_feature(feature)
|
50
|
+
end
|
51
|
+
|
52
|
+
def kill_node(node)
|
53
|
+
@nodes_by_pid.delete(node.pid)
|
54
|
+
# recall that this process explicitly traps INT -> exit 0
|
55
|
+
Process.kill("INT", node.pid)
|
56
|
+
end
|
57
|
+
|
58
|
+
def kill_nodes_with_feature(file, base = @root)
|
59
|
+
if base.has_feature?(file)
|
60
|
+
if base == @root.children[0] || base == @root
|
61
|
+
Zeus.ui.error "One of zeus's dependencies changed. Not killing zeus. You may have to restart the server."
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
kill_node(base)
|
65
|
+
return true
|
66
|
+
else
|
67
|
+
base.children.dup.each do |node|
|
68
|
+
if kill_nodes_with_feature(file, node)
|
69
|
+
base.children.delete(node)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -1,97 +1,71 @@
|
|
1
1
|
module Zeus
|
2
2
|
class Server
|
3
3
|
class ProcessTreeMonitor
|
4
|
+
PID_TYPE = "P"
|
5
|
+
FEATURE_TYPE = "F"
|
4
6
|
|
5
|
-
def
|
7
|
+
def datasource ; @sock ; end
|
8
|
+
def on_datasource_event ; handle_messages ; end
|
9
|
+
def close_child_socket ; @__CHILD__sock.close ; end
|
10
|
+
def close_parent_socket ; @sock.close ; end
|
11
|
+
|
12
|
+
def initialize(file_monitor)
|
6
13
|
@tree = ProcessTree.new
|
14
|
+
@file_monitor = file_monitor
|
15
|
+
|
16
|
+
@sock, @__CHILD__sock = Socket.pair(:UNIX, :DGRAM)
|
7
17
|
end
|
8
18
|
|
9
19
|
def kill_nodes_with_feature(file)
|
10
20
|
@tree.kill_nodes_with_feature(file)
|
11
21
|
end
|
12
22
|
|
13
|
-
def
|
14
|
-
|
23
|
+
def handle_messages
|
24
|
+
50.times { handle_message }
|
25
|
+
rescue Errno::EAGAIN
|
15
26
|
end
|
16
27
|
|
17
|
-
def
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def add_child(node)
|
29
|
-
self.children << node
|
30
|
-
end
|
31
|
-
|
32
|
-
def add_feature(feature)
|
33
|
-
self.features[feature] = true
|
34
|
-
end
|
35
|
-
|
36
|
-
def has_feature?(feature)
|
37
|
-
self.features[feature] == true
|
38
|
-
end
|
39
|
-
|
40
|
-
def inspect
|
41
|
-
"(#{pid}:#{features.size}:[#{children.map(&:inspect).join(",")}])"
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def inspect
|
47
|
-
@root.inspect
|
48
|
-
end
|
49
|
-
|
50
|
-
def initialize
|
51
|
-
@root = Node.new(Process.pid)
|
52
|
-
@nodes_by_pid = {Process.pid => @root}
|
28
|
+
def handle_message
|
29
|
+
data = @sock.recv_nonblock(1024)
|
30
|
+
case data[0]
|
31
|
+
when FEATURE_TYPE
|
32
|
+
handle_feature_message(data[1..-1])
|
33
|
+
when PID_TYPE
|
34
|
+
handle_pid_message(data[1..-1])
|
35
|
+
else
|
36
|
+
raise "Unrecognized message"
|
53
37
|
end
|
38
|
+
end
|
54
39
|
|
55
|
-
|
56
|
-
|
57
|
-
|
40
|
+
def handle_pid_message(data)
|
41
|
+
data =~ /(\d+):(\d+)/
|
42
|
+
pid, ppid = $1.to_i, $2.to_i
|
43
|
+
@tree.process_has_parent(pid, ppid)
|
44
|
+
end
|
58
45
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
46
|
+
def handle_feature_message(data)
|
47
|
+
data =~ /(\d+):(.*)/
|
48
|
+
pid, file = $1.to_i, $2
|
49
|
+
@tree.process_has_feature(pid, file)
|
50
|
+
@file_monitor.watch(file)
|
51
|
+
end
|
64
52
|
|
65
|
-
def process_has_feature(pid, feature)
|
66
|
-
node = node_for_pid(pid)
|
67
|
-
node.add_feature(feature)
|
68
|
-
end
|
69
53
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
54
|
+
module ChildProcessApi
|
55
|
+
def __CHILD__send_pid(message)
|
56
|
+
@__CHILD__sock.send(PID_TYPE + message, 0)
|
57
|
+
rescue Errno::ENOBUFS
|
58
|
+
sleep 0.2
|
59
|
+
retry
|
74
60
|
end
|
75
61
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
kill_node(base)
|
83
|
-
return true
|
84
|
-
else
|
85
|
-
base.children.dup.each do |node|
|
86
|
-
if kill_nodes_with_feature(file, node)
|
87
|
-
base.children.delete(node)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
return false
|
91
|
-
end
|
62
|
+
def __CHILD__send_feature(message)
|
63
|
+
@__CHILD__sock.send(FEATURE_TYPE + message, 0)
|
64
|
+
rescue Errno::ENOBUFS
|
65
|
+
sleep 0.2
|
66
|
+
retry
|
92
67
|
end
|
93
|
-
|
94
|
-
end
|
68
|
+
end ; include ChildProcessApi
|
95
69
|
|
96
70
|
end
|
97
71
|
end
|
data/lib/zeus/server/stage.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Zeus
|
2
2
|
class Server
|
3
|
+
# NONE of the code in the module is run in the master process,
|
4
|
+
# so every communication to the master must be done with IPC.
|
3
5
|
class Stage
|
4
6
|
HasNoChildren = Class.new(Exception)
|
5
7
|
|
@@ -10,7 +12,7 @@ module Zeus
|
|
10
12
|
end
|
11
13
|
|
12
14
|
def notify_feature(feature)
|
13
|
-
@server.
|
15
|
+
@server.__CHILD__pid_has_feature(Process.pid, feature)
|
14
16
|
end
|
15
17
|
|
16
18
|
def descendent_acceptors
|
@@ -43,11 +45,13 @@ module Zeus
|
|
43
45
|
sleep
|
44
46
|
end
|
45
47
|
|
46
|
-
def run
|
48
|
+
def run(close_parent_sockets = false)
|
47
49
|
@pid = fork {
|
50
|
+
# This is only passed to the top-level stage, from Server#run, not sub-stages.
|
51
|
+
@server.__CHILD__close_parent_sockets if close_parent_sockets
|
52
|
+
|
48
53
|
$0 = "zeus spawner: #{@name}"
|
49
|
-
pid
|
50
|
-
@server.w_pid "#{pid}:#{Process.ppid}"
|
54
|
+
@server.__CHILD__pid_has_ppid(Process.pid, Process.ppid)
|
51
55
|
|
52
56
|
Zeus.ui.as_zeus("starting spawner `#{@name}`")
|
53
57
|
trap("INT") {
|
data/lib/zeus/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zeus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- lib/zeus/server/client_handler.rb
|
40
40
|
- lib/zeus/server/file_monitor.rb
|
41
41
|
- lib/zeus/server/file_monitor/fsevent.rb
|
42
|
+
- lib/zeus/server/process_tree.rb
|
42
43
|
- lib/zeus/server/process_tree_monitor.rb
|
43
44
|
- lib/zeus/server/stage.rb
|
44
45
|
- lib/zeus/templates/rails.rb
|