isomorfeus-iodine 0.7.50 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +0 -1
- data/examples/config.ru +56 -56
- data/exe/iodine +64 -277
- data/ext/iodine_ext/fio.c +7 -7
- data/ext/iodine_ext/fio.h +5 -3
- data/ext/iodine_ext/http.c +1 -1
- data/ext/iodine_ext/redis_engine.c +1 -1
- data/isomorfeus-iodine.gemspec +2 -0
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +35 -33
- metadata +32 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1da68cfbc32b4125c4ca8513b8796276b1ea4daa2123517a5fa3ed895ebddf0
|
4
|
+
data.tar.gz: 1cc64c512e725ca4e7fb119c9bc59f2ac6d4edc59ae99e2ca7c4a74beb8fd9de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a04d7a8b0edd83ce7bbb130a43b4655ea0b271ffc99c3d2bd265763899335569ee23abdae992e4082c902989817ded91d5ac529513bb089c5a66e34c984b7daf
|
7
|
+
data.tar.gz: 73dc8cbc81472fb1dacdf38f71cdd75107b8641d64a6f4d0834fa8e7f60126852a767ac64a25d0ca85403cee2d0e80b1fb40f4f24d53210627d1f7c378b3f9a7
|
data/Rakefile
CHANGED
data/examples/config.ru
CHANGED
@@ -1,56 +1,56 @@
|
|
1
|
-
# This is a WebSocket / SSE notification broadcasting application.
|
2
|
-
#
|
3
|
-
# Running this application from the command line is easy with:
|
4
|
-
#
|
5
|
-
# iodine
|
6
|
-
#
|
7
|
-
# Or, in single thread and single process:
|
8
|
-
#
|
9
|
-
# iodine -t 1 -w 1
|
10
|
-
#
|
11
|
-
# Benchmark with `ab` or `wrk` (a 5 seconds benchmark with 2000 concurrent clients):
|
12
|
-
#
|
13
|
-
# ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
|
14
|
-
# wrk -c2000 -d5 -t12 http://localhost:3000/
|
15
|
-
|
16
|
-
|
17
|
-
# A simple router - Checks for Websocket Upgrade and answers HTTP.
|
18
|
-
module MyHTTPRouter
|
19
|
-
# This is the HTTP response object according to the Rack specification.
|
20
|
-
HTTP_RESPONSE = [200, { 'Content-Type' => 'text/html',
|
21
|
-
'Content-Length' => '77' },
|
22
|
-
['Please connect using WebSockets or SSE (send messages only using WebSockets).']]
|
23
|
-
|
24
|
-
WS_RESPONSE = [0, {}, []].freeze
|
25
|
-
|
26
|
-
# this is function will be called by the Rack server (iodine) for every request.
|
27
|
-
def self.call env
|
28
|
-
# check if this is an upgrade request (WebsSocket / SSE).
|
29
|
-
if(env['rack.upgrade?'.freeze])
|
30
|
-
env['rack.upgrade'.freeze] = BroadcastClient
|
31
|
-
return WS_RESPONSE
|
32
|
-
end
|
33
|
-
# simply return the RESPONSE object, no matter what request was received.
|
34
|
-
HTTP_RESPONSE
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# A simple Websocket Callback Object.
|
39
|
-
module BroadcastClient
|
40
|
-
# seng a message to new clients.
|
41
|
-
def on_open client
|
42
|
-
client.subscribe :broadcast
|
43
|
-
end
|
44
|
-
# send a message, letting the client know the server is suggunt down.
|
45
|
-
def on_shutdown client
|
46
|
-
client.write "Server shutting down. Goodbye."
|
47
|
-
end
|
48
|
-
# perform the echo
|
49
|
-
def on_message client, data
|
50
|
-
client.publish :broadcast, data
|
51
|
-
end
|
52
|
-
extend self
|
53
|
-
end
|
54
|
-
|
55
|
-
# this function call links our HelloWorld application with Rack
|
56
|
-
run MyHTTPRouter
|
1
|
+
# This is a WebSocket / SSE notification broadcasting application.
|
2
|
+
#
|
3
|
+
# Running this application from the command line is easy with:
|
4
|
+
#
|
5
|
+
# iodine
|
6
|
+
#
|
7
|
+
# Or, in single thread and single process:
|
8
|
+
#
|
9
|
+
# iodine -t 1 -w 1
|
10
|
+
#
|
11
|
+
# Benchmark with `ab` or `wrk` (a 5 seconds benchmark with 2000 concurrent clients):
|
12
|
+
#
|
13
|
+
# ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
|
14
|
+
# wrk -c2000 -d5 -t12 http://localhost:3000/
|
15
|
+
|
16
|
+
|
17
|
+
# A simple router - Checks for Websocket Upgrade and answers HTTP.
|
18
|
+
module MyHTTPRouter
|
19
|
+
# This is the HTTP response object according to the Rack specification.
|
20
|
+
HTTP_RESPONSE = [200, { 'Content-Type' => 'text/html',
|
21
|
+
'Content-Length' => '77' },
|
22
|
+
['Please connect using WebSockets or SSE (send messages only using WebSockets).']]
|
23
|
+
|
24
|
+
WS_RESPONSE = [0, {}, []].freeze
|
25
|
+
|
26
|
+
# this is function will be called by the Rack server (iodine) for every request.
|
27
|
+
def self.call env
|
28
|
+
# check if this is an upgrade request (WebsSocket / SSE).
|
29
|
+
if(env['rack.upgrade?'.freeze])
|
30
|
+
env['rack.upgrade'.freeze] = BroadcastClient
|
31
|
+
return WS_RESPONSE
|
32
|
+
end
|
33
|
+
# simply return the RESPONSE object, no matter what request was received.
|
34
|
+
HTTP_RESPONSE
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# A simple Websocket Callback Object.
|
39
|
+
module BroadcastClient
|
40
|
+
# seng a message to new clients.
|
41
|
+
def on_open client
|
42
|
+
client.subscribe :broadcast
|
43
|
+
end
|
44
|
+
# send a message, letting the client know the server is suggunt down.
|
45
|
+
def on_shutdown client
|
46
|
+
client.write "Server shutting down. Goodbye."
|
47
|
+
end
|
48
|
+
# perform the echo
|
49
|
+
def on_message client, data
|
50
|
+
client.publish :broadcast, data
|
51
|
+
end
|
52
|
+
extend self
|
53
|
+
end
|
54
|
+
|
55
|
+
# this function call links our HelloWorld application with Rack
|
56
|
+
run MyHTTPRouter
|
data/exe/iodine
CHANGED
@@ -1,277 +1,64 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
IODINE_PARSE_CLI = true
|
4
|
-
require 'iodine'
|
5
|
-
|
6
|
-
# Load Rack if available (assume it will be used)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
require config
|
66
|
-
app = Object.const_get(::File.basename(config, '.rb').split('_').map(&:capitalize).join(''))
|
67
|
-
return app, {}
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.load_file(path, options = Hash.new)
|
72
|
-
cfgfile = ::File.read(path)
|
73
|
-
cfgfile.slice!(/\A#{UTF_8_BOM}/) if cfgfile.encoding == Encoding::UTF_8
|
74
|
-
|
75
|
-
cfgfile.sub!(/^__END__\n.*\Z/m, '')
|
76
|
-
app = new_from_string cfgfile, path
|
77
|
-
|
78
|
-
return app, options
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.new_from_string(builder_script, file = "(rackup)")
|
82
|
-
eval "Iodine::Base::Rack::Builder.new {\n" + builder_script + "\n}.to_app",
|
83
|
-
TOPLEVEL_BINDING, file, 0
|
84
|
-
end
|
85
|
-
|
86
|
-
def initialize(default_app = nil, &block)
|
87
|
-
@use, @map, @run, @warmup, @freeze_app = [], nil, default_app, nil, false
|
88
|
-
instance_eval(&block) if block_given?
|
89
|
-
end
|
90
|
-
|
91
|
-
def self.app(default_app = nil, &block)
|
92
|
-
self.new(default_app, &block).to_app
|
93
|
-
end
|
94
|
-
|
95
|
-
# Specifies middleware to use in a stack.
|
96
|
-
#
|
97
|
-
# class Middleware
|
98
|
-
# def initialize(app)
|
99
|
-
# @app = app
|
100
|
-
# end
|
101
|
-
#
|
102
|
-
# def call(env)
|
103
|
-
# env["rack.some_header"] = "setting an example"
|
104
|
-
# @app.call(env)
|
105
|
-
# end
|
106
|
-
# end
|
107
|
-
#
|
108
|
-
# use Middleware
|
109
|
-
# run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
|
110
|
-
#
|
111
|
-
# All requests through to this application will first be processed by the middleware class.
|
112
|
-
# The +call+ method in this example sets an additional environment key which then can be
|
113
|
-
# referenced in the application if required.
|
114
|
-
def use(middleware, *args, &block)
|
115
|
-
if @map
|
116
|
-
mapping, @map = @map, nil
|
117
|
-
@use << proc { |app| generate_map(app, mapping) }
|
118
|
-
end
|
119
|
-
@use << proc { |app| middleware.new(app, *args, &block) }
|
120
|
-
end
|
121
|
-
|
122
|
-
# Takes an argument that is an object that responds to #call and returns a Rack response.
|
123
|
-
# The simplest form of this is a lambda object:
|
124
|
-
#
|
125
|
-
# run lambda { |env| [200, { "Content-Type" => "text/plain" }, ["OK"]] }
|
126
|
-
#
|
127
|
-
# However this could also be a class:
|
128
|
-
#
|
129
|
-
# class Heartbeat
|
130
|
-
# def self.call(env)
|
131
|
-
# [200, { "Content-Type" => "text/plain" }, ["OK"]]
|
132
|
-
# end
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# run Heartbeat
|
136
|
-
def run(app)
|
137
|
-
@run = app
|
138
|
-
end
|
139
|
-
|
140
|
-
# Takes a lambda or block that is used to warm-up the application.
|
141
|
-
#
|
142
|
-
# warmup do |app|
|
143
|
-
# client = Rack::MockRequest.new(app)
|
144
|
-
# client.get('/')
|
145
|
-
# end
|
146
|
-
#
|
147
|
-
# use SomeMiddleware
|
148
|
-
# run MyApp
|
149
|
-
def warmup(prc = nil, &block)
|
150
|
-
@warmup = prc || block
|
151
|
-
end
|
152
|
-
|
153
|
-
# Creates a route within the application.
|
154
|
-
#
|
155
|
-
# Rack::Builder.app do
|
156
|
-
# map '/' do
|
157
|
-
# run Heartbeat
|
158
|
-
# end
|
159
|
-
# end
|
160
|
-
#
|
161
|
-
# The +use+ method can also be used here to specify middleware to run under a specific path:
|
162
|
-
#
|
163
|
-
# Rack::Builder.app do
|
164
|
-
# map '/' do
|
165
|
-
# use Middleware
|
166
|
-
# run Heartbeat
|
167
|
-
# end
|
168
|
-
# end
|
169
|
-
#
|
170
|
-
# This example includes a piece of middleware which will run before requests hit +Heartbeat+.
|
171
|
-
#
|
172
|
-
def map(path, &block)
|
173
|
-
@map ||= {}
|
174
|
-
@map[path] = block
|
175
|
-
end
|
176
|
-
|
177
|
-
# Freeze the app (set using run) and all middleware instances when building the application
|
178
|
-
# in to_app.
|
179
|
-
def freeze_app
|
180
|
-
@freeze_app = true
|
181
|
-
end
|
182
|
-
|
183
|
-
def to_app
|
184
|
-
app = @map ? generate_map(@run, @map) : @run
|
185
|
-
fail "missing run or map statement" unless app
|
186
|
-
app.freeze if @freeze_app
|
187
|
-
app = @use.reverse.inject(app) { |a, e| e[a].tap { |x| x.freeze if @freeze_app } }
|
188
|
-
@warmup.call(app) if @warmup
|
189
|
-
app
|
190
|
-
end
|
191
|
-
|
192
|
-
def call(env)
|
193
|
-
to_app.call(env)
|
194
|
-
end
|
195
|
-
|
196
|
-
private
|
197
|
-
|
198
|
-
def generate_map(default_app, mapping)
|
199
|
-
mapped = default_app ? { '/' => default_app } : {}
|
200
|
-
mapping.each { |r, b| mapped[r] = self.class.new(default_app, &b).to_app }
|
201
|
-
URLMap.new(mapped)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
module Iodine
|
210
|
-
# The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
|
211
|
-
module Base
|
212
|
-
# Command line interface. The Ruby CLI might be changed in future versions.
|
213
|
-
module CLI
|
214
|
-
|
215
|
-
def self.try_file filename
|
216
|
-
return nil unless File.exist? filename
|
217
|
-
return Iodine::Base::Rack::Builder.parse_file filename
|
218
|
-
end
|
219
|
-
|
220
|
-
def self.get_app_opts
|
221
|
-
app, opt = nil, nil
|
222
|
-
filename = Iodine::DEFAULT_SETTINGS[:filename_]
|
223
|
-
if filename
|
224
|
-
app, opt = try_file filename
|
225
|
-
app, opt = try_file "#{filename}.ru" unless opt
|
226
|
-
unless opt
|
227
|
-
puts "* Couldn't find #{filename}\n testing for config.ru\n"
|
228
|
-
app, opt = try_file "config.ru"
|
229
|
-
end
|
230
|
-
else
|
231
|
-
app, opt = try_file "config.ru";
|
232
|
-
end
|
233
|
-
|
234
|
-
unless opt
|
235
|
-
puts "WARNING: Ruby application not found#{ filename ? " - missing both #{filename} and config.ru" : " - missing config.ru"}."
|
236
|
-
if Iodine::DEFAULT_SETTINGS[:public]
|
237
|
-
puts " Running only static file service."
|
238
|
-
opt = Hash.new
|
239
|
-
app = Proc.new { [404, {}, "Not Found!"] }
|
240
|
-
else
|
241
|
-
puts "\nERROR: Couldn't run Ruby application, check command line arguments."
|
242
|
-
ARGV << "-?"
|
243
|
-
Iodine::Base::CLI.parse
|
244
|
-
exit(0);
|
245
|
-
end
|
246
|
-
end
|
247
|
-
return app, opt
|
248
|
-
end
|
249
|
-
|
250
|
-
def self.perform_warmup(app)
|
251
|
-
# load anything marked with `autoload`, since autoload is niether thread safe nor fork friendly.
|
252
|
-
Iodine.on_state(:on_start) do
|
253
|
-
Module.constants.each do |n|
|
254
|
-
begin
|
255
|
-
Object.const_get(n)
|
256
|
-
rescue StandardError => _e
|
257
|
-
end
|
258
|
-
end
|
259
|
-
Iodine::Base::Rack::Builder.new(app) do |r|
|
260
|
-
r.warmup do |a|
|
261
|
-
client = ::Rack::MockRequest.new(a)
|
262
|
-
client.get('/')
|
263
|
-
end
|
264
|
-
end
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def self.call
|
269
|
-
app, opt = get_app_opts
|
270
|
-
perform_warmup(app) if Iodine::DEFAULT_SETTINGS[:warmup_]
|
271
|
-
Iodine::Rack.run(app, opt)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
Iodine::Base::CLI.call
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
IODINE_PARSE_CLI = true
|
4
|
+
require 'iodine'
|
5
|
+
|
6
|
+
# Load Rack if available (assume it will be used)
|
7
|
+
|
8
|
+
require 'rack'
|
9
|
+
|
10
|
+
module Iodine
|
11
|
+
# The Iodine::Base namespace is reserved for internal use and is NOT part of the public API.
|
12
|
+
module Base
|
13
|
+
# Command line interface. The Ruby CLI might be changed in future versions.
|
14
|
+
module CLI
|
15
|
+
|
16
|
+
def self.try_file filename
|
17
|
+
return nil unless File.exist? filename
|
18
|
+
::Rack::Builder.parse_file filename
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.get_app
|
22
|
+
app = nil
|
23
|
+
filename = Iodine::DEFAULT_SETTINGS[:filename_]
|
24
|
+
if filename
|
25
|
+
app = try_file filename
|
26
|
+
app = try_file "#{filename}.ru" unless app
|
27
|
+
unless app
|
28
|
+
puts "* Couldn't find #{filename}\n testing for config.ru\n"
|
29
|
+
app = try_file "config.ru"
|
30
|
+
end
|
31
|
+
else
|
32
|
+
app = try_file "config.ru";
|
33
|
+
end
|
34
|
+
app
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.perform_warmup(app)
|
38
|
+
# load anything marked with `autoload`, since autoload is niether thread safe nor fork friendly.
|
39
|
+
Iodine.on_state(:on_start) do
|
40
|
+
Module.constants.each do |n|
|
41
|
+
begin
|
42
|
+
Object.const_get(n)
|
43
|
+
rescue StandardError => _e
|
44
|
+
end
|
45
|
+
end
|
46
|
+
::Rack::Builder.new(app) do |r|
|
47
|
+
r.warmup do |a|
|
48
|
+
client = ::Rack::MockRequest.new(a)
|
49
|
+
client.get('/')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.call
|
56
|
+
app = get_app
|
57
|
+
perform_warmup(app) if Iodine::DEFAULT_SETTINGS[:warmup_]
|
58
|
+
Iodine::Rack.run(app)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
Iodine::Base::CLI.call
|
data/ext/iodine_ext/fio.c
CHANGED
@@ -155,7 +155,7 @@ int ioctl (int fd, u_long request, int* argp) {
|
|
155
155
|
else { return 0; }
|
156
156
|
}
|
157
157
|
|
158
|
-
int
|
158
|
+
int fio_kill(int pid, int sig) {
|
159
159
|
/* Credit to Jan Biedermann (GitHub: @janbiedermann) */
|
160
160
|
HANDLE handle;
|
161
161
|
DWORD status;
|
@@ -987,7 +987,7 @@ FIO_FUNC void fio_thread_signal(void) {
|
|
987
987
|
(void)r;
|
988
988
|
} else if (fd == -1) {
|
989
989
|
/* hardly the best way, but there's a thread sleeping on air */
|
990
|
-
|
990
|
+
fio_kill(getpid(), SIGCONT);
|
991
991
|
}
|
992
992
|
#endif
|
993
993
|
}
|
@@ -1654,7 +1654,7 @@ void fio_reap_children(void) {
|
|
1654
1654
|
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
|
1655
1655
|
if (sigaction(SIGCHLD, &sa, &fio_old_sig_chld) == -1) {
|
1656
1656
|
perror("Child reaping initialization failed");
|
1657
|
-
|
1657
|
+
fio_kill(0, SIGINT);
|
1658
1658
|
exit(errno);
|
1659
1659
|
}
|
1660
1660
|
}
|
@@ -4603,7 +4603,7 @@ static void *fio_sentinel_worker_thread(void *arg) {
|
|
4603
4603
|
if (child == -1) {
|
4604
4604
|
FIO_LOG_FATAL("couldn't spawn worker.");
|
4605
4605
|
perror("\n errno");
|
4606
|
-
|
4606
|
+
fio_kill(fio_parent_pid(), SIGINT);
|
4607
4607
|
fio_stop();
|
4608
4608
|
return NULL;
|
4609
4609
|
} else if (child) {
|
@@ -4617,7 +4617,7 @@ static void *fio_sentinel_worker_thread(void *arg) {
|
|
4617
4617
|
} else {
|
4618
4618
|
FIO_LOG_FATAL("Child worker (%d) shutdown. Stopping services.", child);
|
4619
4619
|
}
|
4620
|
-
|
4620
|
+
fio_kill(0, SIGINT);
|
4621
4621
|
}
|
4622
4622
|
#else
|
4623
4623
|
if (fio_data->active) {
|
@@ -6879,7 +6879,7 @@ static void fio_cluster_on_close(intptr_t uuid, fio_protocol_s *pr_) {
|
|
6879
6879
|
#ifndef __MINGW32__
|
6880
6880
|
fio_cluster_data_cleanup(1);
|
6881
6881
|
#endif
|
6882
|
-
|
6882
|
+
fio_kill(getpid(), SIGINT);
|
6883
6883
|
}
|
6884
6884
|
}
|
6885
6885
|
if (c->msg)
|
@@ -7155,7 +7155,7 @@ static void fio_cluster_on_connect(intptr_t uuid, void *udata) {
|
|
7155
7155
|
static void fio_cluster_on_fail(intptr_t uuid, void *udata) {
|
7156
7156
|
FIO_LOG_FATAL("(facil.io) unknown cluster connection error");
|
7157
7157
|
perror(" errno");
|
7158
|
-
|
7158
|
+
fio_kill(fio_parent_pid(), SIGINT);
|
7159
7159
|
fio_stop();
|
7160
7160
|
// exit(errno ? errno : 1);
|
7161
7161
|
(void)udata;
|
data/ext/iodine_ext/fio.h
CHANGED
@@ -263,10 +263,12 @@ Version and helper macros
|
|
263
263
|
#define pipe(fds) _pipe(fds, 65536, _O_BINARY)
|
264
264
|
|
265
265
|
int fork(void);
|
266
|
-
int
|
266
|
+
int fio_kill(int, int);
|
267
267
|
ssize_t pread(int, void*, size_t, off_t);
|
268
268
|
ssize_t pwrite(int, const void *, size_t, off_t);
|
269
269
|
int fio_osffd4fd(unsigned int);
|
270
|
+
#else
|
271
|
+
#define fio_kill kill
|
270
272
|
#endif
|
271
273
|
|
272
274
|
/* *****************************************************************************
|
@@ -523,7 +525,7 @@ FIO_LOG2STDERR(const char *format, ...) {
|
|
523
525
|
if (!(ptr)) { \
|
524
526
|
FIO_LOG_FATAL("memory allocation error "__FILE__ \
|
525
527
|
":" FIO_MACRO2STR(__LINE__)); \
|
526
|
-
|
528
|
+
fio_kill(0, SIGINT); \
|
527
529
|
exit(errno); \
|
528
530
|
}
|
529
531
|
#endif
|
@@ -6048,7 +6050,7 @@ FIO_NAME(_insert_or_overwrite_)(FIO_NAME(s) * set, FIO_SET_HASH_TYPE hash_value,
|
|
6048
6050
|
pos->hash = hash_value;
|
6049
6051
|
pos->pos->hash = hash_value;
|
6050
6052
|
FIO_SET_COPY(pos->pos->obj, obj);
|
6051
|
-
|
6053
|
+
|
6052
6054
|
return pos->pos->obj;
|
6053
6055
|
}
|
6054
6056
|
|
data/ext/iodine_ext/http.c
CHANGED
@@ -922,7 +922,7 @@ intptr_t http_listen(const char *port, const char *binding,
|
|
922
922
|
if (arg_settings.on_request == NULL) {
|
923
923
|
FIO_LOG_ERROR("http_listen requires the .on_request parameter "
|
924
924
|
"to be set\n");
|
925
|
-
|
925
|
+
fio_kill(0, SIGINT);
|
926
926
|
exit(11);
|
927
927
|
}
|
928
928
|
|
@@ -852,7 +852,7 @@ FIO_IGNORE_MACRO(struct redis_engine_create_args args) {
|
|
852
852
|
if (getpid() != fio_parent_pid()) {
|
853
853
|
FIO_LOG_FATAL("(redis) Redis engine initialization can only "
|
854
854
|
"be performed in the Root process.");
|
855
|
-
|
855
|
+
fio_kill(0, SIGINT);
|
856
856
|
fio_stop();
|
857
857
|
return NULL;
|
858
858
|
}
|
data/isomorfeus-iodine.gemspec
CHANGED
@@ -34,6 +34,8 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.requirements << 'TLS requires OpenSSL >= 1.1.0.'
|
35
35
|
spec.requirements << 'Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.'
|
36
36
|
|
37
|
+
spec.add_dependency 'rackup', '~> 0.2.2'
|
38
|
+
spec.add_dependency 'rack', '~> 3.0.0'
|
37
39
|
spec.add_development_dependency 'rake', '~> 13.0', '< 14.0'
|
38
40
|
spec.add_development_dependency 'minitest', '>=5', '< 6.0'
|
39
41
|
spec.add_development_dependency 'rspec', '>=3.9.0', '< 4.0'
|
data/lib/iodine/version.rb
CHANGED
data/lib/rack/handler/iodine.rb
CHANGED
@@ -1,33 +1,35 @@
|
|
1
|
-
require 'iodine' unless defined?(::Iodine::VERSION)
|
2
|
-
|
3
|
-
module Iodine
|
4
|
-
# Iodine's {Iodine::Rack} module provides a Rack complient interface (connecting Iodine to Rack) for an HTTP and Websocket Server.
|
5
|
-
module Rack
|
6
|
-
|
7
|
-
# Runs a Rack app, as par the Rack handler requirements.
|
8
|
-
def self.run(app, options = {})
|
9
|
-
# nested applications... is that a thing?
|
10
|
-
Iodine.listen(service: :http, handler: app, port: options[:Port], address: options[:Host])
|
11
|
-
|
12
|
-
# start Iodine
|
13
|
-
Iodine.start
|
14
|
-
|
15
|
-
true
|
16
|
-
end
|
17
|
-
|
18
|
-
# patches an assumption by Rack, issue #98 code donated by @Shelvak (Néstor Coppi)
|
19
|
-
def self.shutdown
|
20
|
-
Iodine.stop
|
21
|
-
end
|
22
|
-
|
23
|
-
IODINE_RACK_LOADED = true
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
ENV['RACK_HANDLER'] ||= 'iodine'
|
28
|
-
|
29
|
-
begin
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
1
|
+
require 'iodine' unless defined?(::Iodine::VERSION)
|
2
|
+
|
3
|
+
module Iodine
|
4
|
+
# Iodine's {Iodine::Rack} module provides a Rack complient interface (connecting Iodine to Rack) for an HTTP and Websocket Server.
|
5
|
+
module Rack
|
6
|
+
|
7
|
+
# Runs a Rack app, as par the Rack handler requirements.
|
8
|
+
def self.run(app, options = {})
|
9
|
+
# nested applications... is that a thing?
|
10
|
+
Iodine.listen(service: :http, handler: app, port: options[:Port], address: options[:Host])
|
11
|
+
|
12
|
+
# start Iodine
|
13
|
+
Iodine.start
|
14
|
+
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
# patches an assumption by Rack, issue #98 code donated by @Shelvak (Néstor Coppi)
|
19
|
+
def self.shutdown
|
20
|
+
Iodine.stop
|
21
|
+
end
|
22
|
+
|
23
|
+
IODINE_RACK_LOADED = true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
ENV['RACK_HANDLER'] ||= 'iodine'
|
28
|
+
|
29
|
+
begin
|
30
|
+
if defined?(::Rackup::Handler)
|
31
|
+
::Rackup::Handler.register('iodine', Iodine::Rack)
|
32
|
+
::Rackup::Handler.register('Iodine', Iodine::Rack)
|
33
|
+
end
|
34
|
+
rescue StandardError
|
35
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isomorfeus-iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rackup
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.2.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.2.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: rake
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -247,7 +275,7 @@ metadata:
|
|
247
275
|
github_repo: ssh://github.com/isomorfeus/gems
|
248
276
|
source_code_uri: https://github.com/isomorfeus/isomorfeus-iodine
|
249
277
|
post_install_message: |-
|
250
|
-
Thank you for installing Iodine 0.
|
278
|
+
Thank you for installing Iodine 0.8.1.
|
251
279
|
Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations) to Bo, see https://github.com/boazsegev/iodine
|
252
280
|
rdoc_options: []
|
253
281
|
require_paths:
|
@@ -270,7 +298,7 @@ requirements:
|
|
270
298
|
- Ruby >= 2.5.0 recommended.
|
271
299
|
- TLS requires OpenSSL >= 1.1.0.
|
272
300
|
- Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.
|
273
|
-
rubygems_version: 3.
|
301
|
+
rubygems_version: 3.4.0.dev
|
274
302
|
signing_key:
|
275
303
|
specification_version: 4
|
276
304
|
summary: iodine build for Isomorfeus
|