polyphony 0.76 → 0.77
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 +5 -1
- data/Gemfile.lock +1 -1
- data/examples/core/trap1.rb +21 -0
- data/examples/core/trap2.rb +14 -0
- data/ext/polyphony/backend_io_uring.c +5 -1
- data/ext/polyphony/backend_libev.c +5 -0
- data/ext/test_eintr.c +50 -0
- data/lib/polyphony/extensions/fiber.rb +12 -6
- data/lib/polyphony/version.rb +1 -1
- data/test/helper.rb +2 -1
- data/test/stress.rb +1 -1
- data/test/test_fiber.rb +6 -4
- data/test/test_signal.rb +57 -0
- data/test/test_timer.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10f049946dc02d9cdd984cc8658687d2319e0fd85f6f2cce74aa0a887bc714cb
|
4
|
+
data.tar.gz: 5118859d4640aebeddb9186c43d58617e9b455a63ea97c1dc8283432db954fd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e107e21d6c42f9cd9e91521e288dfee37a6f0da4b7d8a8d311924bf88ccf732d2cc94de834dbbaa3c7a974e5bb84ce1d8d20efd68870c9f2dac9b73155d28558
|
7
|
+
data.tar.gz: 8e4f7005c9cbc46cd084bbe66a4e8f7145f6a4a3062ce027a70eee07c0e648f79289515591ef4b48010580b7125c403ab09e45417781346ebf6da4b2d528ec45
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
pid = Process.pid
|
4
|
+
fork do
|
5
|
+
sleep 1
|
6
|
+
Process.kill('SIGINT', pid)
|
7
|
+
# sleep 10
|
8
|
+
# Process.kill(-9, pid)
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'bundler/setup'
|
12
|
+
require 'polyphony'
|
13
|
+
|
14
|
+
Thread.backend.trace_proc = proc { |*e| STDOUT.orig_write("#{e.inspect}\n") }
|
15
|
+
trap('SIGINT') { STDOUT.orig_write("* recv SIGINT\n") }
|
16
|
+
# trap('SIGCHLD') { STDOUT.orig_write("* recv SIGCHLD\n") }
|
17
|
+
STDOUT.orig_write("* pre gets\n")
|
18
|
+
# STDIN.wait_readable
|
19
|
+
s = gets
|
20
|
+
p s
|
21
|
+
STDOUT.orig_write("* post gets\n")
|
@@ -191,10 +191,14 @@ void io_uring_backend_poll(Backend_t *backend) {
|
|
191
191
|
io_uring_submit(&backend->ring);
|
192
192
|
}
|
193
193
|
|
194
|
+
wait_cqe:
|
194
195
|
backend->base.currently_polling = 1;
|
195
196
|
rb_thread_call_without_gvl(io_uring_backend_poll_without_gvl, (void *)&poll_ctx, RUBY_UBF_IO, 0);
|
196
197
|
backend->base.currently_polling = 0;
|
197
|
-
if (poll_ctx.result < 0)
|
198
|
+
if (poll_ctx.result < 0) {
|
199
|
+
if (poll_ctx.result == -EINTR && runqueue_empty_p(&backend->base.runqueue)) goto wait_cqe;
|
200
|
+
return;
|
201
|
+
}
|
198
202
|
|
199
203
|
io_uring_backend_handle_completion(poll_ctx.cqe, backend);
|
200
204
|
io_uring_cqe_seen(&backend->ring, poll_ctx.cqe);
|
@@ -169,9 +169,14 @@ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
|
169
169
|
backend->base.poll_count++;
|
170
170
|
|
171
171
|
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_enter, rb_fiber_current());
|
172
|
+
|
173
|
+
ev_run:
|
172
174
|
backend->base.currently_polling = 1;
|
175
|
+
errno = 0;
|
173
176
|
ev_run(backend->ev_loop, blocking == Qtrue ? EVRUN_ONCE : EVRUN_NOWAIT);
|
174
177
|
backend->base.currently_polling = 0;
|
178
|
+
if (errno == EINTR && runqueue_empty_p(&backend->base.runqueue)) goto ev_run;
|
179
|
+
|
175
180
|
COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_leave, rb_fiber_current());
|
176
181
|
|
177
182
|
return self;
|
data/ext/test_eintr.c
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <unistd.h>
|
3
|
+
#include <signal.h>
|
4
|
+
#include <poll.h>
|
5
|
+
#include "./liburing/liburing.h"
|
6
|
+
|
7
|
+
void sig_handler(int sig) {
|
8
|
+
printf("handle signal %d!\n", sig);
|
9
|
+
}
|
10
|
+
|
11
|
+
int main(int argc, char *argv[])
|
12
|
+
{
|
13
|
+
int pid = getpid();
|
14
|
+
int child_pid = fork();
|
15
|
+
if (!child_pid) {
|
16
|
+
sleep(1);
|
17
|
+
kill(pid, SIGINT);
|
18
|
+
sleep(1);
|
19
|
+
kill(pid, SIGINT);
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
struct sigaction sa;
|
23
|
+
|
24
|
+
sa.sa_handler = sig_handler;
|
25
|
+
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;//0;
|
26
|
+
sigemptyset(&sa.sa_mask);
|
27
|
+
sigaction(SIGINT, &sa, NULL);
|
28
|
+
|
29
|
+
printf("pid: %d\n", pid);
|
30
|
+
|
31
|
+
struct io_uring ring;
|
32
|
+
int ret = io_uring_queue_init(16, &ring, 0);
|
33
|
+
printf("io_uring_queue_init: %d\n", ret);
|
34
|
+
|
35
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
|
36
|
+
io_uring_prep_poll_add(sqe, STDIN_FILENO, POLLIN);
|
37
|
+
ret = io_uring_submit(&ring);
|
38
|
+
printf("io_uring_submit: %d\n", ret);
|
39
|
+
|
40
|
+
struct io_uring_cqe *cqe;
|
41
|
+
|
42
|
+
wait_cqe:
|
43
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
44
|
+
printf("io_uring_wait_cqe: %d\n", ret);
|
45
|
+
if (ret == -EINTR) goto wait_cqe;
|
46
|
+
|
47
|
+
printf("done\n");
|
48
|
+
return 0;
|
49
|
+
}
|
50
|
+
}
|
@@ -248,21 +248,27 @@ module Polyphony
|
|
248
248
|
# also be scheduled with priority. This method is mainly used trapping
|
249
249
|
# signals (see also the patched `Kernel#trap`)
|
250
250
|
def schedule_priority_oob_fiber(&block)
|
251
|
-
|
251
|
+
oob_fiber = Fiber.new do
|
252
252
|
Fiber.current.setup_raw
|
253
253
|
result = block.call
|
254
254
|
rescue Exception => e
|
255
255
|
Thread.current.schedule_and_wakeup(Thread.main.main_fiber, e)
|
256
256
|
result = e
|
257
257
|
ensure
|
258
|
-
Thread.backend.trace(:fiber_terminate,
|
258
|
+
Thread.backend.trace(:fiber_terminate, Fiber.current, result)
|
259
259
|
suspend
|
260
260
|
end
|
261
|
-
|
261
|
+
prepare_oob_fiber(oob_fiber, block)
|
262
|
+
Thread.backend.trace(:fiber_create, oob_fiber)
|
263
|
+
oob_fiber.schedule_with_priority(nil)
|
264
|
+
end
|
265
|
+
|
266
|
+
def prepare_oob_fiber(fiber, block)
|
267
|
+
fiber.oob = true
|
268
|
+
fiber.tag = :oob
|
269
|
+
fiber.thread = Thread.current
|
262
270
|
location = block.source_location
|
263
|
-
|
264
|
-
Thread.backend.trace(:fiber_create, f)
|
265
|
-
Thread.current.schedule_and_wakeup(f, nil)
|
271
|
+
fiber.set_caller(["#{location.join(':')}"])
|
266
272
|
end
|
267
273
|
end
|
268
274
|
|
data/lib/polyphony/version.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -46,10 +46,11 @@ class MiniTest::Test
|
|
46
46
|
Thread.current.backend.finalize
|
47
47
|
Thread.current.backend = Polyphony::Backend.new
|
48
48
|
sleep 0.001
|
49
|
+
@__stamp = Time.now
|
49
50
|
end
|
50
51
|
|
51
52
|
def teardown
|
52
|
-
# trace "* teardown #{self.name}"
|
53
|
+
# trace "* teardown #{self.name} (#{Time.now - @__stamp}s)"
|
53
54
|
Fiber.current.shutdown_all_children
|
54
55
|
if Fiber.current.children.size > 0
|
55
56
|
puts "Children left after #{self.name}: #{Fiber.current.children.inspect}"
|
data/test/stress.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
count = ARGV[0] ? ARGV[0].to_i : 100
|
4
4
|
test_name = ARGV[1]
|
5
5
|
|
6
|
-
$test_cmd = +'ruby test/run.rb --name
|
6
|
+
$test_cmd = +'ruby test/run.rb --name test_cross_thread_send_receive'
|
7
7
|
if test_name
|
8
8
|
$test_cmd << " --name #{test_name}"
|
9
9
|
end
|
data/test/test_fiber.rb
CHANGED
@@ -923,18 +923,20 @@ class MailboxTest < MiniTest::Test
|
|
923
923
|
def test_cross_thread_send_receive
|
924
924
|
ping_receive_buffer = []
|
925
925
|
pong_receive_buffer = []
|
926
|
+
master = Fiber.current
|
926
927
|
|
927
928
|
pong = Thread.new do
|
928
|
-
|
929
|
-
|
929
|
+
master << :pong_ready
|
930
|
+
3.times do
|
930
931
|
peer, data = receive
|
931
932
|
pong_receive_buffer << data
|
932
933
|
peer << 'pong'
|
933
934
|
end
|
934
935
|
end
|
935
936
|
|
937
|
+
assert_equal :pong_ready, receive
|
938
|
+
|
936
939
|
ping = Thread.new do
|
937
|
-
sleep 0.05
|
938
940
|
3.times do
|
939
941
|
pong << [Fiber.current, 'ping']
|
940
942
|
data = receive
|
@@ -943,7 +945,7 @@ class MailboxTest < MiniTest::Test
|
|
943
945
|
end
|
944
946
|
|
945
947
|
ping.join
|
946
|
-
pong.
|
948
|
+
pong.join
|
947
949
|
ping = pong = nil
|
948
950
|
|
949
951
|
assert_equal %w{pong pong pong}, ping_receive_buffer
|
data/test/test_signal.rb
CHANGED
@@ -3,6 +3,63 @@
|
|
3
3
|
require_relative 'helper'
|
4
4
|
|
5
5
|
class SignalTrapTest < Minitest::Test
|
6
|
+
def test_signal_handler_trace
|
7
|
+
i1, o1 = IO.pipe
|
8
|
+
i2, o2 = IO.pipe
|
9
|
+
pid = Process.pid
|
10
|
+
child_pid = Polyphony.fork do
|
11
|
+
i1.gets
|
12
|
+
Process.kill('SIGINT', pid)
|
13
|
+
sleep 0.1
|
14
|
+
o2.puts "done"
|
15
|
+
o2.close
|
16
|
+
end
|
17
|
+
|
18
|
+
events = []
|
19
|
+
begin
|
20
|
+
Thread.backend.trace_proc = proc { |*e| events << [e[0], e[1].tag] }
|
21
|
+
trap ('SIGINT') { }
|
22
|
+
|
23
|
+
o1.orig_write("\n")
|
24
|
+
o1.close
|
25
|
+
|
26
|
+
msg = i2.gets
|
27
|
+
assert_equal "done\n", msg
|
28
|
+
ensure
|
29
|
+
Thread.backend.trace_proc = nil
|
30
|
+
trap ('SIGINT') { raise Interrupt }
|
31
|
+
end
|
32
|
+
|
33
|
+
Fiber.current.tag = :main
|
34
|
+
|
35
|
+
expected = [
|
36
|
+
[:fiber_switchpoint, :main],
|
37
|
+
[:fiber_event_poll_enter, :main],
|
38
|
+
[:fiber_create, :oob],
|
39
|
+
[:fiber_schedule, :oob],
|
40
|
+
[:fiber_event_poll_leave, :main],
|
41
|
+
[:fiber_run, :oob],
|
42
|
+
[:fiber_terminate, :oob],
|
43
|
+
[:fiber_switchpoint, :oob],
|
44
|
+
[:fiber_event_poll_enter, :oob],
|
45
|
+
[:fiber_schedule, :main],
|
46
|
+
[:fiber_event_poll_leave, :oob],
|
47
|
+
[:fiber_run, :main]
|
48
|
+
]
|
49
|
+
if Thread.backend.kind == :libev
|
50
|
+
expected += [
|
51
|
+
[:fiber_schedule, :main],
|
52
|
+
[:fiber_switchpoint, :main],
|
53
|
+
[:fiber_run, :main]
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
assert_equal expected, events
|
58
|
+
ensure
|
59
|
+
Process.kill('SIGTERM', child_pid) rescue nil
|
60
|
+
Process.wait(child_pid) rescue nil
|
61
|
+
end
|
62
|
+
|
6
63
|
def test_int_signal
|
7
64
|
Thread.new { sleep 0.001; Process.kill('INT', Process.pid) }
|
8
65
|
assert_raises(Interrupt) { sleep 5 }
|
data/test/test_timer.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polyphony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.77'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -245,6 +245,8 @@ files:
|
|
245
245
|
- examples/core/thread_pool.rb
|
246
246
|
- examples/core/throttling.rb
|
247
247
|
- examples/core/timeout.rb
|
248
|
+
- examples/core/trap1.rb
|
249
|
+
- examples/core/trap2.rb
|
248
250
|
- examples/core/using-a-mutex.rb
|
249
251
|
- examples/core/worker-thread.rb
|
250
252
|
- examples/io/backticks.rb
|
@@ -346,6 +348,7 @@ files:
|
|
346
348
|
- ext/polyphony/runqueue_ring_buffer.h
|
347
349
|
- ext/polyphony/socket_extensions.c
|
348
350
|
- ext/polyphony/thread.c
|
351
|
+
- ext/test_eintr.c
|
349
352
|
- lib/polyphony.rb
|
350
353
|
- lib/polyphony/adapters/fs.rb
|
351
354
|
- lib/polyphony/adapters/irb.rb
|