uninterruptible 2.4.1 → 2.5.0
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 +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/uninterruptible/file_descriptor_server.rb +2 -2
- data/lib/uninterruptible/server.rb +43 -39
- data/lib/uninterruptible/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72a22a5770c97eab497ced8af3b4ef1eb1969954
|
4
|
+
data.tar.gz: 697a74b90a5f7f1e9fa0e4bd0c099e4565de8c4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35f6725ea1ed919a3ea884840bbd9462d26c451d1efa380a3c7b707427dae2be667b1eb2ffd006915b27371bcbfa897e04e2971b029fce0d72f7f7f32288ecc0
|
7
|
+
data.tar.gz: 2a0e883d4ebad0dab294743349d01d851f69e00d279746bdb6e4a35444893706b1ceb66223174685834ea14a380f8f7e436015c85a1415845760c3e1f099f2cc
|
data/CHANGELOG.md
CHANGED
@@ -16,7 +16,7 @@ module Uninterruptible
|
|
16
16
|
|
17
17
|
# @return [String] Location on disk where socket server is listening
|
18
18
|
def socket_path
|
19
|
-
@socket_path ||= File.join(socket_directory, '
|
19
|
+
@socket_path ||= File.join(socket_directory, 'fd.sock')
|
20
20
|
end
|
21
21
|
|
22
22
|
# Accept the next client connection and send it the file descriptor
|
@@ -41,7 +41,7 @@ module Uninterruptible
|
|
41
41
|
private
|
42
42
|
|
43
43
|
def socket_directory
|
44
|
-
@socket_directory ||= Dir.mktmpdir('
|
44
|
+
@socket_directory ||= Dir.mktmpdir('u-')
|
45
45
|
end
|
46
46
|
|
47
47
|
def start_socket_server
|
@@ -30,7 +30,7 @@ module Uninterruptible
|
|
30
30
|
module Server
|
31
31
|
def self.included(base)
|
32
32
|
base.class_eval do
|
33
|
-
attr_reader :active_connections, :socket_server, :signal_pipe_r, :signal_pipe_w, :mutex
|
33
|
+
attr_reader :active_connections, :socket_server, :signal_pipe_r, :signal_pipe_w, :mutex, :file_descriptor_server
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -52,9 +52,15 @@ module Uninterruptible
|
|
52
52
|
|
53
53
|
logger.info "Starting server on #{server_configuration.bind}"
|
54
54
|
|
55
|
-
|
55
|
+
# Set up each listener and add it to an array ready for the event loop
|
56
|
+
@active_descriptors = []
|
57
|
+
@active_descriptors << establish_socket_server
|
58
|
+
@active_descriptors << establish_file_descriptor_server
|
59
|
+
@active_descriptors << setup_signal_traps
|
60
|
+
|
56
61
|
write_pidfile
|
57
|
-
|
62
|
+
|
63
|
+
# Enter the main loop
|
58
64
|
select_loop
|
59
65
|
end
|
60
66
|
|
@@ -72,15 +78,31 @@ module Uninterruptible
|
|
72
78
|
# signal_pipe_r for processing any signals sent to the process.
|
73
79
|
def select_loop
|
74
80
|
loop do
|
75
|
-
|
76
|
-
readable.
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
81
|
+
# Wait for descriptors or a 1 second timeout
|
82
|
+
readable, = IO.select(@active_descriptors, [], [], 1)
|
83
|
+
# Only process one descriptor per iteration.
|
84
|
+
# We don't want to process a descriptor that has been deleted.
|
85
|
+
reader = readable&.first
|
86
|
+
if reader == signal_pipe_r
|
87
|
+
signal = reader.gets.chomp
|
88
|
+
process_signal(signal)
|
89
|
+
elsif reader == file_descriptor_server.socket_server
|
90
|
+
file_descriptor_server.serve_file_descriptor
|
91
|
+
@active_descriptors.delete(file_descriptor_server.socket_server)
|
92
|
+
graceful_shutdown
|
93
|
+
elsif reader == socket_server
|
94
|
+
accept_client_connection
|
95
|
+
end
|
96
|
+
|
97
|
+
if @shutdown
|
98
|
+
if active_connections.zero?
|
99
|
+
logger.debug "No more active connections. Exiting'"
|
100
|
+
Process.exit(0)
|
101
|
+
else
|
102
|
+
logger.debug "#{active_connections} connections still active"
|
82
103
|
end
|
83
104
|
end
|
105
|
+
|
84
106
|
end
|
85
107
|
end
|
86
108
|
|
@@ -119,22 +141,18 @@ module Uninterruptible
|
|
119
141
|
# in the env, reconnect to that file descriptor.
|
120
142
|
def establish_socket_server
|
121
143
|
@socket_server = Uninterruptible::Binder.new(server_configuration.bind).bind_to_socket
|
122
|
-
# If there's a file descriptor present, take over from a previous instance of this server and kill it off
|
123
|
-
kill_parent if ENV[FILE_DESCRIPTOR_SERVER_VAR]
|
124
|
-
|
125
|
-
@socket_server.autoclose = false
|
126
|
-
@socket_server.close_on_exec = false
|
127
144
|
|
128
145
|
if server_configuration.tls_enabled?
|
129
146
|
@socket_server = Uninterruptible::TLSServerFactory.new(server_configuration).wrap_with_tls(@socket_server)
|
130
147
|
end
|
148
|
+
@socket_server
|
131
149
|
end
|
132
150
|
|
133
|
-
#
|
134
|
-
#
|
135
|
-
def
|
136
|
-
|
137
|
-
|
151
|
+
# Create the UNIX socket server that will pass the server file descriptor
|
152
|
+
# to the child process when a restart occurs.
|
153
|
+
def establish_file_descriptor_server
|
154
|
+
@file_descriptor_server = FileDescriptorServer.new(socket_server)
|
155
|
+
@file_descriptor_server.socket_server
|
138
156
|
end
|
139
157
|
|
140
158
|
# Write the current pid out to pidfile_path if configured
|
@@ -155,6 +173,7 @@ module Uninterruptible
|
|
155
173
|
@signal_pipe_w.puts(signal_name)
|
156
174
|
end
|
157
175
|
end
|
176
|
+
@signal_pipe_r
|
158
177
|
end
|
159
178
|
|
160
179
|
# When a signal has been caught, it should be passed here for the appropriate action to be taken
|
@@ -164,12 +183,11 @@ module Uninterruptible
|
|
164
183
|
# @param [String] signal_name Signal to process
|
165
184
|
def process_signal(signal_name)
|
166
185
|
if signal_name == 'TERM'
|
167
|
-
if
|
186
|
+
if @shutdown
|
168
187
|
logger.info "TERM received again, exiting immediately"
|
169
|
-
Process.exit(1)
|
188
|
+
Process.exit(1)
|
170
189
|
else
|
171
190
|
logger.info "TERM received, starting graceful shutdown"
|
172
|
-
$shutdown = true
|
173
191
|
graceful_shutdown
|
174
192
|
end
|
175
193
|
elsif signal_name == 'USR1'
|
@@ -181,22 +199,12 @@ module Uninterruptible
|
|
181
199
|
# Stop listening on socket_server, wait until all active connections have finished processing and exit with 0.
|
182
200
|
def graceful_shutdown
|
183
201
|
socket_server.close unless socket_server.closed?
|
184
|
-
|
185
|
-
|
186
|
-
logger.debug "#{active_connections} connections still active"
|
187
|
-
sleep 0.5
|
188
|
-
end
|
189
|
-
|
190
|
-
logger.debug "No more active connections. Exiting'"
|
191
|
-
|
192
|
-
Process.exit(0)
|
202
|
+
@active_descriptors.delete(socket_server)
|
203
|
+
@shutdown = true
|
193
204
|
end
|
194
205
|
|
195
206
|
# Start a new copy of this server, maintaining all current file descriptors and env.
|
196
207
|
def hot_restart
|
197
|
-
# Start a FileDescriptorServer running on a unix socket
|
198
|
-
file_descriptor_server = FileDescriptorServer.new(socket_server)
|
199
|
-
|
200
208
|
fork do
|
201
209
|
# Let the new server know where to find the file descriptor server
|
202
210
|
ENV[FILE_DESCRIPTOR_SERVER_VAR] = file_descriptor_server.socket_path
|
@@ -206,10 +214,6 @@ module Uninterruptible
|
|
206
214
|
|
207
215
|
exec("bundle exec #{server_configuration.start_command}")
|
208
216
|
end
|
209
|
-
|
210
|
-
# Provide the new server with the file descriptor for @socket_server
|
211
|
-
file_descriptor_server.serve_file_descriptor
|
212
|
-
file_descriptor_server.close
|
213
217
|
end
|
214
218
|
|
215
219
|
def network_restrictions
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uninterruptible
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Wentworth
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|