kino 0.1.3 → 0.2.1
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 +19 -0
- data/Cargo.lock +115 -123
- data/Cargo.toml +6 -2
- data/README.md +26 -1
- data/ext/kino/Cargo.toml +3 -3
- data/ext/kino/src/gvl.rs +41 -8
- data/ext/kino/src/lib.rs +5 -0
- data/ext/kino/src/pin.rs +223 -0
- data/ext/kino/src/queue.rs +19 -17
- data/ext/kino/src/registry.rs +4 -0
- data/ext/kino/src/request.rs +20 -6
- data/ext/kino/src/server.rs +12 -0
- data/ext/kino/src/test_support.rs +13 -1
- data/ext/kino/src/timer.rs +1 -1
- data/lib/kino/server.rb +87 -12
- data/lib/kino/version.rb +1 -1
- metadata +3 -2
data/ext/kino/src/timer.rs
CHANGED
data/lib/kino/server.rb
CHANGED
|
@@ -73,17 +73,28 @@ module Kino
|
|
|
73
73
|
def start
|
|
74
74
|
raise Error, "server already started" if @started
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
# Claim the pidfile before binding: refusing to start (another
|
|
77
|
+
# instance is alive) must not leave a booted native runtime behind.
|
|
78
|
+
write_pidfile if @pidfile
|
|
79
|
+
booted = false
|
|
80
|
+
begin
|
|
81
|
+
@id, @port = Native.server_start(
|
|
82
|
+
bind: @bind, port: @requested_port,
|
|
83
|
+
queue_depth: @queue_depth, queue_timeout_ms: @queue_timeout_ms,
|
|
84
|
+
request_timeout_ms: @request_timeout_ms,
|
|
85
|
+
max_connections: @max_connections,
|
|
86
|
+
max_body_size: @max_body_size,
|
|
87
|
+
tokio_threads: @tokio_threads,
|
|
88
|
+
tls_cert: @tls&.fetch(:cert), tls_key: @tls&.fetch(:key),
|
|
89
|
+
lanes: @lanes, log_requests: @log_requests
|
|
90
|
+
)
|
|
91
|
+
booted = true
|
|
92
|
+
ensure
|
|
93
|
+
remove_pidfile if @pidfile && !booted
|
|
94
|
+
end
|
|
95
|
+
# GC anchor for zero-copy response buffers: held for the server's
|
|
96
|
+
# lifetime so in-flight buffers survive even a worker ractor crash.
|
|
97
|
+
@pin_keeper = Native.pin_keeper(@id)
|
|
87
98
|
if @mode == :ractor
|
|
88
99
|
@supervisor = RactorSupervisor.new(@id, @app, workers: @workers, threads: @threads,
|
|
89
100
|
batch: @batch, on_error: @on_error).start
|
|
@@ -133,9 +144,12 @@ module Kino
|
|
|
133
144
|
end
|
|
134
145
|
|
|
135
146
|
Native.shutdown_runtime(@id, 1_000)
|
|
147
|
+
# The runtime is gone, so hyper has dropped every pinned buffer;
|
|
148
|
+
# the keeper (and the strings it marked) may now be collected.
|
|
149
|
+
@pin_keeper = nil
|
|
136
150
|
@worker_threads.clear
|
|
137
151
|
@started = false
|
|
138
|
-
|
|
152
|
+
remove_pidfile if @pidfile
|
|
139
153
|
nil
|
|
140
154
|
end
|
|
141
155
|
|
|
@@ -241,6 +255,67 @@ module Kino
|
|
|
241
255
|
[soft * 8 / 10, 64].max
|
|
242
256
|
end
|
|
243
257
|
|
|
258
|
+
# Claim the pidfile for this process. O_EXCL creation fails on ANY
|
|
259
|
+
# existing directory entry (regular file, symlink, even a dangling
|
|
260
|
+
# one), so a live instance's pidfile is never overwritten and a
|
|
261
|
+
# symlink is never followed. A leftover entry whose owner is gone is
|
|
262
|
+
# replaced; one that does not hold a pid is refused, not clobbered.
|
|
263
|
+
def write_pidfile
|
|
264
|
+
claim_pidfile
|
|
265
|
+
rescue Errno::EEXIST
|
|
266
|
+
refuse_unless_stale
|
|
267
|
+
begin
|
|
268
|
+
# Unlink removes the entry itself; a symlink's target is untouched.
|
|
269
|
+
File.unlink(@pidfile)
|
|
270
|
+
rescue Errno::ENOENT
|
|
271
|
+
# Vanished on its own; the claim below settles any remaining race.
|
|
272
|
+
end
|
|
273
|
+
begin
|
|
274
|
+
claim_pidfile
|
|
275
|
+
rescue Errno::EEXIST
|
|
276
|
+
raise Error, "lost the race for #{@pidfile}: another instance is starting"
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def claim_pidfile
|
|
281
|
+
File.open(@pidfile, File::WRONLY | File::CREAT | File::EXCL, 0o644) do |file|
|
|
282
|
+
file.write("#{Process.pid}\n")
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# @raise [Kino::Error] when the pidfile's owner is still alive, or the
|
|
287
|
+
# file does not look like a pidfile at all
|
|
288
|
+
def refuse_unless_stale
|
|
289
|
+
content = begin
|
|
290
|
+
File.read(@pidfile)
|
|
291
|
+
rescue Errno::ENOENT
|
|
292
|
+
return # already gone; nothing to refuse
|
|
293
|
+
end
|
|
294
|
+
pid = Integer(content.strip, exception: false)
|
|
295
|
+
unless pid&.positive?
|
|
296
|
+
raise Error, "refusing to overwrite #{@pidfile}: does not hold a pid"
|
|
297
|
+
end
|
|
298
|
+
raise Error, "already running (pid #{pid}, per #{@pidfile})" if process_alive?(pid)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def process_alive?(pid)
|
|
302
|
+
Process.kill(0, pid)
|
|
303
|
+
true
|
|
304
|
+
rescue Errno::ESRCH
|
|
305
|
+
false
|
|
306
|
+
rescue Errno::EPERM
|
|
307
|
+
true # exists, just not ours to signal
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Delete only a pidfile that is still ours: by shutdown time the path
|
|
311
|
+
# may belong to a replacement instance, or an operator may have
|
|
312
|
+
# repointed it at something that is not a pidfile at all.
|
|
313
|
+
def remove_pidfile
|
|
314
|
+
File.unlink(@pidfile) if File.read(@pidfile) == "#{Process.pid}\n"
|
|
315
|
+
rescue Errno::ENOENT
|
|
316
|
+
nil
|
|
317
|
+
end
|
|
318
|
+
|
|
244
319
|
def join_workers(deadline)
|
|
245
320
|
if @supervisor
|
|
246
321
|
@supervisor.shutdown([deadline - monotonic_now, 0].max)
|
data/lib/kino/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kino
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yaroslav Markin
|
|
@@ -165,6 +165,7 @@ files:
|
|
|
165
165
|
- ext/kino/src/gvl.rs
|
|
166
166
|
- ext/kino/src/lib.rs
|
|
167
167
|
- ext/kino/src/logsink.rs
|
|
168
|
+
- ext/kino/src/pin.rs
|
|
168
169
|
- ext/kino/src/queue.rs
|
|
169
170
|
- ext/kino/src/registry.rs
|
|
170
171
|
- ext/kino/src/request.rs
|
|
@@ -213,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
213
214
|
- !ruby/object:Gem::Version
|
|
214
215
|
version: '0'
|
|
215
216
|
requirements: []
|
|
216
|
-
rubygems_version: 4.0.
|
|
217
|
+
rubygems_version: 4.0.16
|
|
217
218
|
specification_version: 4
|
|
218
219
|
summary: High-performance Ractor web server for Ruby.
|
|
219
220
|
test_files: []
|