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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ad0cf72d2ae4acd2673cff5b4c5a2fa627cd2833e3131fa4504a2dc1e4cef6ea
4
- data.tar.gz: 69bb3e3bf2dfdffc3806c442a1d095b018f865f6c3d966ce7f5b4d789ba2bc9f
3
+ metadata.gz: 10f049946dc02d9cdd984cc8658687d2319e0fd85f6f2cce74aa0a887bc714cb
4
+ data.tar.gz: 5118859d4640aebeddb9186c43d58617e9b455a63ea97c1dc8283432db954fd1
5
5
  SHA512:
6
- metadata.gz: 306e7c56b5fa00a078e725e508bf99934f6ea12c738cb1e1c66130b20037ad4862f8aeefe0a53fec214387579955dfde9f74b92487653af8f501c80a6a16bb1b
7
- data.tar.gz: 3c807f56e677355ae3193db5a641caa660ab2f18cc2d7a5f8a4b38ef2b59463b0bf732cf4878cd7c93e19198f1eb330797b82f1ea69089f5ec055a3545e4d04c
6
+ metadata.gz: e107e21d6c42f9cd9e91521e288dfee37a6f0da4b7d8a8d311924bf88ccf732d2cc94de834dbbaa3c7a974e5bb84ce1d8d20efd68870c9f2dac9b73155d28558
7
+ data.tar.gz: 8e4f7005c9cbc46cd084bbe66a4e8f7145f6a4a3062ce027a70eee07c0e648f79289515591ef4b48010580b7125c403ab09e45417781346ebf6da4b2d528ec45
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
+ ## 0.77 2022-02-07
2
+
3
+ - Fix behaviour of signal traps (#71)
4
+
1
5
  ## 0.76 2022-02-06
2
6
 
3
- - Comment out `Backend_close` API
7
+ - Comment out `Backend_close` API (#70)
4
8
 
5
9
  ## 0.75 2022-02-04
6
10
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.76)
4
+ polyphony (0.77)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -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")
@@ -0,0 +1,14 @@
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
+ trap('SIGINT') {}
12
+ p :before
13
+ result = IO.select([STDIN])
14
+ p :after
@@ -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) return;
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
- f = Fiber.new do
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, f, result)
258
+ Thread.backend.trace(:fiber_terminate, Fiber.current, result)
259
259
  suspend
260
260
  end
261
- f.oob = true
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
- f.set_caller(["#{location.join(':')}"])
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.76'
4
+ VERSION = '0.77'
5
5
  end
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 test_receive_cross_thread_exception'
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
- sleep 0.05
929
- loop do
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.kill
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
@@ -78,7 +78,7 @@ class TimerCancelAfterTest < MiniTest::Test
78
78
 
79
79
  def test_timer_cancel_after_with_reset
80
80
  buf = []
81
- @timer.cancel_after(0.13) do
81
+ @timer.cancel_after(0.15) do
82
82
  sleep 0.05
83
83
  buf << 1
84
84
  @timer.reset
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.76'
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-06 00:00:00.000000000 Z
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