polyphony 0.67 → 0.68

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b8553a2f84e79520ce53412ee6891873c9a9d25e0789e82b26a7153d3d7ae67
4
- data.tar.gz: 6889ef71f11d79d6fbb82adc77447f9b3526a29858f2aa3c9e51ee9098add2c7
3
+ metadata.gz: d23a9c0f60530fdee1d367f34359e4f694bd4a42ba3c0112e61433df05c29a81
4
+ data.tar.gz: bf75e3f1a633f5c94a43fd45a2de2545d87b1e751753980abb8e1d3eddd4eade
5
5
  SHA512:
6
- metadata.gz: 91814f767f74c673681a2215f82a302f3aab5ced6ae7197720e474b8c1ad6846eb10001580c1f11d5b62bd0ed7563422fd71f0fb5728eb0b3fcb4ebd36d2038c
7
- data.tar.gz: 74e1c7ed34b4f212ca1ffd5881da3e9f689c3934d0f3680da2396d7444b5a214a610ccc779c1ef59713116f0a8240491dc60f32b5d5e30de5092ddc41b8c9f18
6
+ metadata.gz: b810c7ddbd383039e5f34fe76dbea089807417d4415e79a952f6d6a46538cf99c55ae7a34f3eadf61d22af23ac29a0910c62ea5c97dff6e86b94083d98444edf
7
+ data.tar.gz: '063459edd8f669a024e0b7b8f1daa47983db4cf9ac7f3ca81a69359de92eace4831d843e9b74645db08a50c26d83a2878a5fdb6b125adc260afd13a3135e710c'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.68 2021-08-13
2
+
3
+ - Fix missing default value in socket classes' `#readpartial`
4
+ - Fix linking of operations in `Backend#chain` (io_uring version)
5
+ - Rename `Fiber#attach` to `Fiber#attach_to`
6
+ - Expose original `SSLServer#accept`
7
+
1
8
  ## 0.67 2021-08-06
2
9
 
3
10
  - Improve fiber monitoring
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.67)
4
+ polyphony (0.68)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/bin/pdbg CHANGED
@@ -8,23 +8,105 @@ UNIX_SOCKET_PATH = '/tmp/pdbg.sock'
8
8
 
9
9
  cmd = ARGV.join(' ')
10
10
  injected_lib_path = File.expand_path('../lib/polyphony/debugger/server_inject.rb', __dir__)
11
- p cmd
12
11
  pid = fork { exec("env POLYPHONY_DEBUG_SOCKET_PATH=#{UNIX_SOCKET_PATH} ruby #{cmd}") }
13
12
  puts "Started debugged process (#{pid})"
14
13
 
15
- sleep 3
16
- socket = UNIXSocket.new(UNIX_SOCKET_PATH)
14
+ socket = nil
15
+ while !socket
16
+ socket = UNIXSocket.new(UNIX_SOCKET_PATH) rescue nil
17
+ end
18
+
19
+ def parse_command(cmd)
20
+ case cmd
21
+ when /^(step|s)$/
22
+ { cmd: :step }
23
+ when /^(state|st)$/
24
+ { cmd: :state }
25
+ when /^(help|h)$/
26
+ { cmd: :help }
27
+ when /^(list|l)$/
28
+ { cmd: :list }
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def display_info(info)
35
+ info = eval(info)
36
+ case (info && info[:kind])
37
+ when :listing
38
+ print_listing(info)
39
+ when :state
40
+ print_state(info)
41
+ else
42
+ p info
43
+ end
44
+ rescue SyntaxError
45
+ puts "Failed to eval:"
46
+ p info
47
+ end
48
+
49
+ FILE_LINES_CACHE = {}
50
+
51
+ def self.get_snippet(path, lineno)
52
+ lines = FILE_LINES_CACHE[path] ||= IO.read(path).lines
53
+ start_idx = lineno - 5
54
+ stop_idx = lineno + 3
55
+ stop_idx = lines.size - 1 if stop_idx >= lines.size
56
+ start_idx = 0 if start_idx < 0
57
+ (start_idx..stop_idx).map { |idx| [idx + 1, lines[idx]]}
58
+ end
59
+
60
+ def print_snippet(info, snippet, cur_line)
61
+ places = FILE_LINES_CACHE[info[:path]].size.to_s.size
62
+ snippet.each do |(lineno, line)|
63
+ is_cur = lineno == cur_line
64
+ formatted = format("%s% #{places}d %s", is_cur ? '=> ' : ' ', lineno, line)
65
+ puts formatted
66
+ end
67
+ end
68
+
69
+ def print_listing(info)
70
+ snippet = get_snippet(info[:path], info[:lineno])
71
+ puts "Fiber: #{info[:fiber]} Location: #{info[:path]}:#{info[:lineno]}"
72
+ puts
73
+ print_snippet(info, snippet, info[:lineno])
74
+ puts
75
+ end
76
+
77
+ def print_help
78
+ puts
79
+ puts "Here's some help..."
80
+ puts
81
+ end
82
+
83
+ def print_state(info)
84
+ p info
85
+ end
86
+
87
+ def get_user_cmd
88
+ while true
89
+ STDOUT << "(pdbg) "
90
+ cmd = parse_command(STDIN.gets)
91
+ next unless cmd
92
+
93
+ if cmd[:cmd] == :help
94
+ print_help
95
+ else
96
+ return cmd if cmd
97
+ end
98
+ end
99
+ end
100
+
17
101
  socket.puts 'pdbg'
18
102
  response = socket.gets
19
103
  if response.chomp == 'pdbg'
20
104
  puts 'Connected to process'
21
105
  end
22
106
  loop do
23
- status = socket.gets
24
- puts status
107
+ info = socket.gets.chomp
108
+ display_info(info)
25
109
 
26
- STDOUT << "> "
27
- cmd = STDIN.gets
28
- puts '-' * 40
29
- socket.puts cmd
110
+ cmd = get_user_cmd
111
+ socket.puts cmd.inspect
30
112
  end
@@ -1248,7 +1248,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
1248
1248
  }
1249
1249
 
1250
1250
  io_uring_sqe_set_data(last_sqe, ctx);
1251
- unsigned int flags = (i == argc - 1) ? IOSQE_ASYNC : IOSQE_ASYNC & IOSQE_IO_LINK;
1251
+ unsigned int flags = (i == (argc - 1)) ? IOSQE_ASYNC : IOSQE_ASYNC | IOSQE_IO_LINK;
1252
1252
  io_uring_sqe_set_flags(last_sqe, flags);
1253
1253
  sqe_count++;
1254
1254
  }
data/lib/polyphony.rb CHANGED
@@ -124,6 +124,6 @@ Polyphony.install_at_exit_handler
124
124
 
125
125
  if (debug_socket_path = ENV['POLYPHONY_DEBUG_SOCKET_PATH'])
126
126
  puts "Starting debug server on #{debug_socket_path}"
127
- require 'polyphony/debugger/server'
128
- Polyphony::DebugServer.start(debug_socket_path)
127
+ require 'polyphony/debugger'
128
+ Polyphony.start_debug_server(debug_socket_path)
129
129
  end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'polyphony/extensions/debug'
4
+
5
+ module Polyphony
6
+ TP_EVENTS = [
7
+ :line,
8
+ :call,
9
+ :return,
10
+ :b_call,
11
+ :b_return
12
+ ]
13
+
14
+ def self.start_debug_server(socket_path)
15
+ server = DebugServer.new(socket_path)
16
+ controller = DebugController.new(server)
17
+ trace = TracePoint.new(*TP_EVENTS) { |tp| controller.handle_tp(trace, tp) }
18
+ trace.enable
19
+
20
+ at_exit do
21
+ Kernel.trace "program terminated"
22
+ trace.disable
23
+ server.stop
24
+ end
25
+ end
26
+
27
+ class DebugController
28
+ def initialize(server)
29
+ @server = server
30
+ @server.wait_for_client
31
+ @state = { fibers: {} }
32
+ @control_fiber = Fiber.new { |f| control_loop(f) }
33
+ @control_fiber.transfer Fiber.current
34
+ end
35
+
36
+ def control_loop(source_fiber)
37
+ @peer = source_fiber
38
+ cmd = { cmd: :initial }
39
+ loop do
40
+ cmd = send(:"cmd_#{cmd[:cmd]}", cmd)
41
+ end
42
+ end
43
+
44
+ POLYPHONY_LIB_DIR = File.expand_path('..', __dir__)
45
+
46
+ def get_next_trace_event
47
+ @peer.transfer.tap { |e| update_state(e) }
48
+ end
49
+
50
+ def update_state(event)
51
+ trace update_state: event
52
+ @state[:fiber] = event[:fiber]
53
+ @state[:path] = event[:path]
54
+ @state[:lineno] = event[:lineno]
55
+ update_fiber_state(event)
56
+ end
57
+
58
+ def update_fiber_state(event)
59
+ fiber_state = @state[:fibers][event[:fiber]] ||= { stack: [] }
60
+ case event[:kind]
61
+ when :call, :c_call, :b_call
62
+ fiber_state[:stack] << event
63
+ when :return, :c_return, :b_return
64
+ fiber_state[:stack].pop
65
+ end
66
+ fiber_state[:binding] = event[:binding]
67
+ fiber_state[:path] = event[:path]
68
+ fiber_state[:lineno] = event[:lineno]
69
+ end
70
+
71
+ def state_presentation(state)
72
+ {
73
+ fiber: fiber_id(state[:fiber]),
74
+ path: state[:path],
75
+ lineno: state[:lineno]
76
+ }
77
+ end
78
+
79
+ def fiber_id(fiber)
80
+ {
81
+ object_id: fiber.object_id,
82
+ tag: fiber.tag
83
+ }
84
+ end
85
+
86
+ def fiber_representation(fiber)
87
+ {
88
+ object_id: fiber.object_id,
89
+ tag: fiber.tag,
90
+ parent: fiber.parent && fiber_id(fiber.parent),
91
+ children: fiber.children.map { |c| fiber_id(c) }
92
+ }
93
+ end
94
+
95
+ def get_next_command(info)
96
+ @server.get_command(info)
97
+ end
98
+
99
+ def cmd_initial(cmd)
100
+ get_next_command(nil)
101
+ end
102
+
103
+ def info_listing(state)
104
+ {
105
+ kind: :listing,
106
+ fiber: fiber_id(state[:fiber]),
107
+ path: state[:path],
108
+ lineno: state[:lineno]
109
+ }
110
+ end
111
+
112
+ def info_state(state)
113
+ info_listing(state).merge(
114
+ kind: :state,
115
+ fibers: info_fiber_states(state[:fibers])
116
+ )
117
+ end
118
+
119
+ def info_fiber_states(fiber_states)
120
+ fiber_states.inject({}) do |h, (f, s)|
121
+ h[fiber_id(f)] = {
122
+ stack: s[:stack].map { |e| { path: e[:path], lineno: e[:lineno] } }
123
+ }
124
+ h
125
+ end
126
+ end
127
+
128
+ def cmd_step(cmd)
129
+ tp = nil
130
+ fiber = nil
131
+ while true
132
+ event = get_next_trace_event
133
+ @peer = event[:fiber]
134
+ if event[:kind] == :line && event[:path] !~ /#{POLYPHONY_LIB_DIR}/
135
+ return get_next_command(info_listing(@state))
136
+ end
137
+ end
138
+ rescue => e
139
+ trace "Uncaught error: #{e.inspect}"
140
+ @trace&.disable
141
+ end
142
+
143
+ def cmd_help(cmd)
144
+ get_next_command(kind: :help)
145
+ end
146
+
147
+ def cmd_list(cmd)
148
+ get_next_command(info_listing(@state))
149
+ end
150
+
151
+ def cmd_state(cmd)
152
+ get_next_command(info_state(@state))
153
+ end
154
+
155
+ def handle_tp(trace, tp)
156
+ return if Thread.current == @server.thread
157
+ return if Fiber.current == @control_fiber
158
+
159
+ kind = tp.event
160
+ event = {
161
+ fiber: Fiber.current,
162
+ kind: kind,
163
+ path: tp.path,
164
+ lineno: tp.lineno,
165
+ binding: tp.binding
166
+ }
167
+ case kind
168
+ when :call, :c_call, :b_call
169
+ event[:method_id] = tp.method_id
170
+ event[:parameters] = tp.parameters
171
+ when :return, :c_return, :b_return
172
+ event[:method_id] = tp.method_id
173
+ event[:return_value] = tp.return_value
174
+ end
175
+ @control_fiber.transfer(event)
176
+ end
177
+ end
178
+
179
+ class DebugServer
180
+ attr_reader :thread
181
+
182
+ def initialize(socket_path)
183
+ @socket_path = socket_path
184
+ @fiber = Fiber.current
185
+ start_server_thread
186
+ end
187
+
188
+ def start_server_thread
189
+ @thread = Thread.new do
190
+ puts("Listening on #{@socket_path}")
191
+ FileUtils.rm(@socket_path) if File.exists?(@socket_path)
192
+ socket = UNIXServer.new(@socket_path)
193
+ loop do
194
+ @client = socket.accept
195
+ end
196
+ end
197
+ end
198
+
199
+ def stop
200
+ @thread.kill
201
+ end
202
+
203
+ def handle_client(client)
204
+ @client = client
205
+ end
206
+
207
+ def wait_for_client
208
+ sleep 0.1 until @client
209
+ msg = @client.gets
210
+ @client.puts msg
211
+ end
212
+
213
+ def get_command(info)
214
+ @client&.orig_write "#{info.inspect}\n"
215
+ cmd = @client&.orig_gets&.chomp
216
+ eval(cmd)
217
+ rescue SystemCallError
218
+ nil
219
+ rescue => e
220
+ trace "Error in interact_with_client: #{e.inspect}"
221
+ e.backtrace[0..3].each { |l| trace l }
222
+ @client = nil
223
+ end
224
+ end
225
+ end
@@ -79,47 +79,26 @@ module Polyphony
79
79
 
80
80
  # Fiber supervision
81
81
  module FiberSupervision
82
- def supervise(opts = {})
83
- @counter = 0
84
- @on_child_done = proc do |fiber, result|
85
- self << fiber unless result.is_a?(Exception)
86
- end
87
- while true
88
- supervise_perform(opts)
89
- end
90
- rescue Polyphony::MoveOn
91
- # generated in #supervise_perform to stop supervisor
92
- ensure
93
- @on_child_done = nil
94
- end
82
+ def supervise(*fibers, **opts, &block)
83
+ block ||= opts[:on_done] ||
84
+ (opts[:on_error] && supervise_on_error_proc(opts[:on_error]))
85
+ raise "No block given" unless block
95
86
 
96
- def supervise_perform(opts)
97
- fiber = receive
98
- if fiber && opts[:restart]
99
- restart_fiber(fiber, opts)
100
- elsif Fiber.current.children.empty?
101
- Fiber.current.stop
87
+ fibers.each do |f|
88
+ f.attach_to(self) unless f.parent == self
89
+ f.monitor(self)
102
90
  end
103
- rescue Polyphony::Restart
104
- restart_all_children
105
- rescue Exception => e
106
- Kernel.raise e if e.source_fiber.nil? || e.source_fiber == self
107
91
 
108
- if opts[:restart]
109
- restart_fiber(e.source_fiber, opts)
110
- elsif Fiber.current.children.empty?
111
- Fiber.current.stop
92
+ mailbox = monitor_mailbox
93
+
94
+ while true
95
+ (fiber, result) = mailbox.shift
96
+ block&.call(fiber, result)
112
97
  end
113
98
  end
114
99
 
115
- def restart_fiber(fiber, opts)
116
- opts[:watcher]&.send [:restart, fiber]
117
- case opts[:restart]
118
- when true
119
- fiber.restart
120
- when :one_for_all
121
- @children.keys.each(&:restart)
122
- end
100
+ def supervise_on_error_proc(on_error)
101
+ ->(f, r) { opts[:on_error].(f, r) if r.is_a?(Exception) }
123
102
  end
124
103
  end
125
104
 
@@ -261,10 +240,17 @@ module Polyphony
261
240
  @parent.add_child(self)
262
241
  end
263
242
 
264
- def attach(parent)
243
+ def attach_to(fiber)
265
244
  @parent.remove_child(self)
266
- @parent = parent
267
- @parent.add_child(self)
245
+ @parent = fiber
246
+ fiber.add_child(self)
247
+ end
248
+
249
+ def attach_and_monitor(fiber)
250
+ @parent.remove_child(self)
251
+ @parent = fiber
252
+ fiber.add_child(self)
253
+ monitor(fiber)
268
254
  end
269
255
  end
270
256
 
@@ -160,8 +160,6 @@ class ::IO
160
160
  return @read_buffer.slice!(0, idx + sep_size) if idx
161
161
 
162
162
  result = readpartial(8192, @read_buffer, -1)
163
-
164
- #Polyphony.backend_read(self, @read_buffer, 8192, false, -1)
165
163
  return nil unless result
166
164
  end
167
165
  rescue EOFError
@@ -114,6 +114,68 @@ end
114
114
 
115
115
  # OpenSSL socket helper methods (to make it compatible with Socket API) and overrides
116
116
  class ::OpenSSL::SSL::SSLServer
117
+ attr_reader :ctx
118
+
119
+ alias_method :orig_accept, :accept
120
+ def accept
121
+ # when @ctx.servername_cb is set, we use a worker thread to run the
122
+ # ssl.accept call. We need to do this because:
123
+ # - We cannot switch fibers inside of the servername_cb proc (see
124
+ # https://github.com/ruby/openssl/issues/415)
125
+ # - We don't want to stop the world while we're busy provisioning an ACME
126
+ # certificate
127
+ if @use_accept_worker.nil?
128
+ if (@use_accept_worker = use_accept_worker_thread?)
129
+ start_accept_worker_thread
130
+ end
131
+ end
132
+
133
+ sock, = @svr.accept
134
+ begin
135
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
136
+ ssl.sync_close = true
137
+ if @use_accept_worker
138
+ @accept_worker_fiber << [ssl, Fiber.current]
139
+ receive
140
+ else
141
+ ssl.accept
142
+ end
143
+ ssl
144
+ rescue Exception => ex
145
+ if ssl
146
+ ssl.close
147
+ else
148
+ sock.close
149
+ end
150
+ raise ex
151
+ end
152
+ end
153
+
154
+ def start_accept_worker_thread
155
+ fiber = Fiber.current
156
+ @accept_worker_thread = Thread.new do
157
+ fiber << Fiber.current
158
+ loop do
159
+ socket, peer = receive
160
+ socket.accept
161
+ peer << socket
162
+ rescue => e
163
+ peer.schedule(e) if fiber
164
+ end
165
+ end
166
+ @accept_worker_fiber = receive
167
+ end
168
+
169
+ def use_accept_worker_thread?
170
+ !!@ctx.servername_cb
171
+ end
172
+
173
+ alias_method :orig_close, :close
174
+ def close
175
+ @accept_worker_thread&.kill
176
+ orig_close
177
+ end
178
+
117
179
  def accept_loop(ignore_errors = true)
118
180
  loop do
119
181
  yield accept
@@ -206,7 +206,7 @@ class ::TCPSocket
206
206
  # Polyphony.backend_send(self, mesg, 0)
207
207
  # end
208
208
 
209
- def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof)
209
+ def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof = true)
210
210
  result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
211
211
  raise EOFError if !result && raise_on_eof
212
212
  result
@@ -299,7 +299,7 @@ class ::UNIXSocket
299
299
  Polyphony.backend_send(self, mesg, 0)
300
300
  end
301
301
 
302
- def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof)
302
+ def readpartial(maxlen, str = +'', buffer_pos = 0, raise_on_eof = true)
303
303
  result = Polyphony.backend_recv(self, str, maxlen, buffer_pos)
304
304
  raise EOFError if !result && raise_on_eof
305
305
  result
data/lib/polyphony/net.rb CHANGED
@@ -67,6 +67,7 @@ module Polyphony
67
67
  def setup_alpn(context, protocols)
68
68
  context.alpn_protocols = protocols
69
69
  context.alpn_select_cb = lambda do |peer_protocols|
70
+ p alpn_select_cb: peer_protocols
70
71
  (protocols & peer_protocols).first
71
72
  end
72
73
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.67'
4
+ VERSION = '0.68'
5
5
  end
data/test/helper.rb CHANGED
@@ -47,7 +47,6 @@ class MiniTest::Test
47
47
  def setup
48
48
  # trace "* setup #{self.name}"
49
49
  Fiber.current.setup_main_fiber
50
- Fiber.current.instance_variable_set(:@auto_watcher, nil)
51
50
  Thread.current.backend.finalize
52
51
  Thread.current.backend = Polyphony::Backend.new
53
52
  sleep 0.001
data/test/test_fiber.rb CHANGED
@@ -791,7 +791,7 @@ class FiberTest < MiniTest::Test
791
791
  ], buf
792
792
  end
793
793
 
794
- def test_attach
794
+ def test_attach_to
795
795
  buf = []
796
796
  child = nil
797
797
  parent = spin(:parent) do
@@ -809,7 +809,7 @@ class FiberTest < MiniTest::Test
809
809
 
810
810
  snooze
811
811
  assert_equal parent, child.parent
812
- child.attach(new_parent)
812
+ child.attach_to(new_parent)
813
813
  assert_equal new_parent, child.parent
814
814
  parent.await
815
815
 
@@ -2,29 +2,29 @@
2
2
 
3
3
  require_relative 'helper'
4
4
 
5
- # class SuperviseTest < MiniTest::Test
6
- # def test_supervise
7
- # p = spin { supervise }
8
- # snooze
9
- # f1 = p.spin { receive }
10
- # f2 = p.spin { receive }
11
-
12
- # snooze
13
- # assert_equal p.state, :waiting
14
- # f1 << 'foo'
15
- # f1.await
16
- # snooze
17
-
18
- # assert_equal :waiting, p.state
19
- # assert_equal :waiting, f2.state
20
-
21
- # f2 << 'bar'
22
- # f2.await
23
- # assert_equal :runnable, p.state
24
-
25
- # 3.times { snooze }
26
- # assert_equal :dead, p.state
27
- # end
5
+ class SuperviseTest < MiniTest::Test
6
+ def test_supervise_with_no_arguments
7
+ assert_raises(RuntimeError) do
8
+ supervise
9
+ end
10
+ end
11
+
12
+ def test_supervise_with_block
13
+ buffer = []
14
+ f1 = spin(:f1) { receive }
15
+ f2 = spin(:f2) { receive }
16
+ supervisor = spin(:supervisor) { supervise(f1, f2) { |*args| buffer << args } }
17
+
18
+ snooze
19
+ f1 << 'foo'
20
+ f1.await
21
+ 10.times { snooze }
22
+ assert_equal [[f1, 'foo']], buffer
23
+
24
+ f2 << 'bar'
25
+ f2.await
26
+ assert_equal [[f1, 'foo'], [f2, 'bar']], buffer
27
+ end
28
28
 
29
29
  # def test_supervise_with_restart
30
30
  # watcher = spin { receive }
@@ -101,4 +101,4 @@ require_relative 'helper'
101
101
  # assert :dead, f.state
102
102
  # assert :dead, p.state
103
103
  # end
104
- # end
104
+ end
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.67'
4
+ version: '0.68'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-06 00:00:00.000000000 Z
11
+ date: 2021-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -357,7 +357,7 @@ files:
357
357
  - lib/polyphony/core/thread_pool.rb
358
358
  - lib/polyphony/core/throttler.rb
359
359
  - lib/polyphony/core/timer.rb
360
- - lib/polyphony/debugger/server.rb
360
+ - lib/polyphony/debugger.rb
361
361
  - lib/polyphony/extensions/core.rb
362
362
  - lib/polyphony/extensions/debug.rb
363
363
  - lib/polyphony/extensions/fiber.rb
@@ -421,7 +421,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
421
421
  - !ruby/object:Gem::Version
422
422
  version: '0'
423
423
  requirements: []
424
- rubygems_version: 3.1.6
424
+ rubygems_version: 3.1.4
425
425
  signing_key:
426
426
  specification_version: 4
427
427
  summary: Fine grained concurrency for Ruby
@@ -1,137 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'polyphony/extensions/debug'
4
-
5
- module Polyphony
6
- class DebugServer
7
- TP_EVENTS = [
8
- :line,
9
- :call,
10
- :return,
11
- :b_call,
12
- :b_return
13
- ]
14
-
15
-
16
- def self.start(socket_path)
17
- server = self.new(socket_path)
18
- server.start
19
-
20
- trace = TracePoint.new(*TP_EVENTS) { |tp| server.handle_tp(trace, tp) }
21
- trace.enable
22
-
23
- at_exit do
24
- puts "program terminated"
25
- trace.disable
26
- server.stop
27
- end
28
- end
29
-
30
- def initialize(socket_path)
31
- @socket_path = socket_path
32
- @fiber = Fiber.current
33
- @controller = spin { control_loop }
34
- puts "@fiber: #{@fiber.inspect}"
35
- end
36
-
37
- def start
38
- fiber = Fiber.current
39
- @server = spin(:pdbg_server) do
40
- puts("Listening on #{@socket_path}")
41
- FileUtils.rm(@socket_path) if File.exists?(@socket_path)
42
- socket = UNIXServer.new(@socket_path)
43
- fiber << :ready
44
- id = 0
45
- socket.accept_loop do |client|
46
- puts "accepted connection"
47
- handle_client(client)
48
- end
49
- end
50
- receive
51
- end
52
-
53
- def stop
54
- @server.terminate
55
- @controller.terminate
56
- end
57
-
58
- POLYPHONY_LIB_DIR = File.expand_path('../..', __dir__)
59
- def handle_client(client)
60
- @client = client
61
- puts "trace enabled"
62
- end
63
-
64
- def control_loop
65
- @cmd = :step
66
- loop do
67
- case @cmd
68
- when :step
69
- step
70
- end
71
- end
72
- end
73
-
74
- def step
75
- tp = nil
76
- fiber = nil
77
- while true
78
- event = receive
79
- fiber = event[:fiber]
80
- if fiber == @fiber && event[:kind] == :line && event[:path] !~ /#{POLYPHONY_LIB_DIR}/
81
- interact_with_client(event)
82
- fiber << :ok
83
- fiber.__unpark__
84
- return
85
- end
86
-
87
- fiber << :ok
88
- fiber.__unpark__
89
- end
90
- rescue => e
91
- puts "Uncaught error: #{e.inspect}"
92
- @trace&.disable
93
- @client = nil
94
- end
95
-
96
- def interact_with_client(event)
97
- @client.puts event.inspect
98
- result = @client.gets&.chomp
99
- end
100
-
101
- def handle_tp(trace, tp)
102
- return if @in_handle_tp
103
-
104
- process_tp(trace, tp)
105
- end
106
-
107
- def process_tp(trace, tp)
108
- @in_handle_tp = true
109
- if !@client
110
- wait_for_client
111
- end
112
-
113
- puts "- #{tp.event} #{tp.path}:#{tp.lineno}"
114
-
115
- fiber = Fiber.current
116
- fiber.__park__
117
-
118
- @controller << {
119
- fiber: fiber,
120
- kind: tp.event,
121
- path: tp.path,
122
- lineno: tp.lineno
123
- }
124
- receive
125
- ensure
126
- @in_handle_tp = nil
127
- end
128
-
129
- def wait_for_client
130
- puts "wait_for_client"
131
- sleep 0.1 until @client
132
- puts " got client!"
133
- msg = @client.gets
134
- @client.puts msg
135
- end
136
- end
137
- end