polyphony 0.67 → 0.68

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: 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