polyphony 0.46.0 → 0.46.1
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 +7 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +22 -9
- data/bin/test +4 -0
- data/examples/performance/fiber_transfer.rb +13 -4
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +7 -18
- data/ext/polyphony/backend_common.h +11 -0
- data/ext/polyphony/backend_io_uring.c +49 -14
- data/ext/polyphony/backend_libev.c +35 -0
- data/ext/polyphony/fiber.c +1 -6
- data/ext/polyphony/polyphony.h +4 -1
- data/ext/polyphony/thread.c +1 -3
- data/lib/polyphony/core/exceptions.rb +0 -4
- data/lib/polyphony/core/global_api.rb +8 -3
- data/lib/polyphony/extensions/core.rb +9 -15
- data/lib/polyphony/extensions/openssl.rb +6 -0
- data/lib/polyphony/extensions/socket.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/helper.rb +1 -1
- data/test/stress.rb +1 -1
- data/test/test_backend.rb +11 -0
- data/test/test_global_api.rb +13 -0
- data/test/test_queue.rb +1 -1
- data/test/test_socket.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 831c85a16a22fe3877044430a4d1cc4a270d18dc73e9ceca8d4826623ab0ddc8
|
4
|
+
data.tar.gz: f0432473abb769be2805ad354dddf44465789ebe2d5220f194660e4c6521ec87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9bfecbed04a8052c3a885dfde73975694313801d2a8341260041be84e4910ac459af71766f7df6fa96e5afad66a737b97e36531811bd47cab407ad43b239e073
|
7
|
+
data.tar.gz: 2caa40f7193cf1954b69adc5810844ad4e578a4472382602a6ee4204d548e8327344f913bc0aef076030e7deacb911cab1733b281f7a2e8849ffcbd009a00ebc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 0.46.1
|
2
|
+
|
3
|
+
* Add `TCPServer#accept_loop`, `OpenSSL::SSL::SSLSocket#accept_loop` method
|
4
|
+
* Fix compilation error on MacOS (#43)
|
5
|
+
* Fix backtrace for `Timeout.timeout`
|
6
|
+
* Add `Backend#timer_loop`
|
7
|
+
|
1
8
|
## 0.46.0
|
2
9
|
|
3
10
|
* Implement [io_uring backend](https://github.com/digital-fabric/polyphony/pull/44)
|
data/Gemfile.lock
CHANGED
data/TODO.md
CHANGED
@@ -1,16 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
-
|
4
|
-
-
|
5
|
-
-
|
6
|
-
-
|
1
|
+
## Roadmap for Polyphony 1.0
|
2
|
+
|
3
|
+
- Check why worker-thread example doesn't work.
|
4
|
+
- Add test that mimics the original design for Monocrono:
|
5
|
+
- 256 fibers each waiting for a message
|
6
|
+
- When message received do some blocking work using a `ThreadPool`
|
7
|
+
- Send messages, collect responses, check for correctness
|
7
8
|
- Improve `#supervise`. It does not work as advertised, and seems to exhibit an
|
8
9
|
inconsistent behaviour (see supervisor example).
|
9
|
-
- Fix backtrace for `Timeout.timeout` API (see timeout example).
|
10
|
-
- Check why worker-thread example doesn't work.
|
11
10
|
|
12
|
-
|
11
|
+
- io_uring
|
12
|
+
- Use playground.c to find out why we when submitting and waiting for
|
13
|
+
completion in single syscall signals seem to be blocked until the syscall
|
14
|
+
returns. Is this a bug in io_uring/liburing?
|
13
15
|
|
16
|
+
-----------------------------------------------------
|
17
|
+
|
18
|
+
- Add `Backend#splice(in, out, nbytes)` API
|
19
|
+
- Adapter for io/console (what does `IO#raw` do?)
|
20
|
+
- Adapter for Pry and IRB (Which fixes #5 and #6)
|
21
|
+
- allow backend selection at runtime
|
14
22
|
- Debugging
|
15
23
|
- Eat your own dogfood: need a good tool to check what's going on when some
|
16
24
|
test fails
|
@@ -148,6 +156,11 @@
|
|
148
156
|
- `IO.foreach`
|
149
157
|
- `Process.waitpid`
|
150
158
|
|
159
|
+
### Quic / HTTP/3
|
160
|
+
|
161
|
+
- Python impl: https://github.com/aiortc/aioquic/
|
162
|
+
- Go impl: https://github.com/lucas-clemente/quic-go
|
163
|
+
|
151
164
|
### DNS client
|
152
165
|
|
153
166
|
```ruby
|
data/bin/test
ADDED
@@ -12,6 +12,7 @@ end
|
|
12
12
|
def run(num_fibers)
|
13
13
|
count = 0
|
14
14
|
|
15
|
+
GC.start
|
15
16
|
GC.disable
|
16
17
|
|
17
18
|
first = nil
|
@@ -36,13 +37,21 @@ def run(num_fibers)
|
|
36
37
|
last.next = first
|
37
38
|
|
38
39
|
t0 = Time.now
|
40
|
+
puts "start transfer..."
|
39
41
|
first.transfer
|
40
42
|
elapsed = Time.now - t0
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
+
rss = `ps -o rss= -p #{Process.pid}`.to_i
|
45
|
+
|
46
|
+
puts "fibers: #{num_fibers} rss: #{rss} count: #{count} rate: #{count / elapsed}"
|
47
|
+
rescue Exception => e
|
48
|
+
puts "Stopped at #{count} fibers"
|
49
|
+
p e
|
44
50
|
end
|
45
51
|
|
52
|
+
puts "pid: #{Process.pid}"
|
46
53
|
run(100)
|
47
|
-
run(1000)
|
48
|
-
run(10000)
|
54
|
+
# run(1000)
|
55
|
+
# run(10000)
|
56
|
+
# run(100000)
|
57
|
+
# run(400000)
|
@@ -4,41 +4,30 @@ require 'bundler/setup'
|
|
4
4
|
require 'polyphony'
|
5
5
|
require 'http/parser'
|
6
6
|
|
7
|
-
$connection_count = 0
|
8
|
-
|
9
7
|
def handle_client(socket)
|
10
|
-
|
8
|
+
pending_requests = []
|
11
9
|
parser = Http::Parser.new
|
12
|
-
|
13
|
-
|
14
|
-
reqs << Object.new # parser
|
15
|
-
end
|
10
|
+
parser.on_message_complete = proc { pending_requests << parser }
|
11
|
+
|
16
12
|
socket.recv_loop do |data|
|
17
13
|
parser << data
|
18
|
-
|
19
|
-
handle_request(socket, req)
|
20
|
-
req = nil
|
21
|
-
end
|
14
|
+
write_response(socket) while pending_requests.shift
|
22
15
|
end
|
23
16
|
rescue IOError, SystemCallError => e
|
24
17
|
# do nothing
|
25
18
|
ensure
|
26
|
-
$connection_count -= 1
|
27
19
|
socket&.close
|
28
20
|
end
|
29
21
|
|
30
|
-
def
|
22
|
+
def write_response(socket)
|
31
23
|
status_code = "200 OK"
|
32
24
|
data = "Hello world!\n"
|
33
25
|
headers = "Content-Type: text/plain\r\nContent-Length: #{data.bytesize}\r\n"
|
34
|
-
|
26
|
+
socket.write "HTTP/1.1 #{status_code}\r\n#{headers}\r\n#{data}"
|
35
27
|
end
|
36
28
|
|
37
29
|
server = TCPServer.open('0.0.0.0', 1234)
|
38
30
|
puts "pid #{Process.pid}"
|
39
31
|
puts "listening on port 1234"
|
40
32
|
|
41
|
-
|
42
|
-
client = server.accept
|
43
|
-
spin { handle_client(client) }
|
44
|
-
end
|
33
|
+
server.accept_loop { |c| handle_client(c) }
|
@@ -1,3 +1,5 @@
|
|
1
|
+
#include <time.h>
|
2
|
+
|
1
3
|
#include "ruby.h"
|
2
4
|
#include "ruby/io.h"
|
3
5
|
|
@@ -107,3 +109,12 @@ inline void rectify_io_file_pos(rb_io_t *fptr) {
|
|
107
109
|
fptr->rbuf.len = 0;
|
108
110
|
}
|
109
111
|
}
|
112
|
+
|
113
|
+
inline double current_time() {
|
114
|
+
struct timespec ts;
|
115
|
+
clock_gettime(CLOCK_MONOTONIC, &ts);
|
116
|
+
long long ns = ts.tv_sec;
|
117
|
+
ns = ns * 1000000000 + ts.tv_nsec;
|
118
|
+
double t = ns;
|
119
|
+
return t / 1e9;
|
120
|
+
}
|
@@ -7,18 +7,18 @@
|
|
7
7
|
#include <fcntl.h>
|
8
8
|
#include <netinet/in.h>
|
9
9
|
#include <arpa/inet.h>
|
10
|
-
|
11
|
-
#include "polyphony.h"
|
12
|
-
#include "../liburing/liburing.h"
|
13
|
-
#include "ruby/thread.h"
|
14
|
-
#include "backend_io_uring_context.h"
|
15
|
-
|
10
|
+
#include <stdnoreturn.h>
|
16
11
|
#include <poll.h>
|
17
12
|
#include <sys/types.h>
|
18
13
|
#include <sys/eventfd.h>
|
19
14
|
#include <sys/wait.h>
|
20
15
|
#include <errno.h>
|
21
16
|
|
17
|
+
#include "polyphony.h"
|
18
|
+
#include "../liburing/liburing.h"
|
19
|
+
#include "ruby/thread.h"
|
20
|
+
#include "backend_io_uring_context.h"
|
21
|
+
|
22
22
|
#ifndef __NR_pidfd_open
|
23
23
|
#define __NR_pidfd_open 434 /* System call # on most architectures */
|
24
24
|
#endif
|
@@ -304,6 +304,7 @@ int io_uring_backend_defer_submit_and_await(
|
|
304
304
|
|
305
305
|
if (value_ptr) (*value_ptr) = switchpoint_result;
|
306
306
|
RB_GC_GUARD(switchpoint_result);
|
307
|
+
RB_GC_GUARD(ctx->fiber);
|
307
308
|
return ctx->result;
|
308
309
|
}
|
309
310
|
|
@@ -773,29 +774,62 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
773
774
|
return self;
|
774
775
|
}
|
775
776
|
|
776
|
-
|
777
|
-
|
778
|
-
struct io_uring_sqe *sqe;
|
777
|
+
// returns true if completed, 0 otherwise
|
778
|
+
int io_uring_backend_submit_timeout_and_await(Backend_t *backend, double duration, VALUE *resume_value) {
|
779
779
|
double duration_integral;
|
780
|
-
double duration_fraction = modf(
|
780
|
+
double duration_fraction = modf(duration, &duration_integral);
|
781
781
|
struct __kernel_timespec ts;
|
782
782
|
|
783
|
-
|
784
|
-
sqe = io_uring_get_sqe(&backend->ring);
|
783
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
785
784
|
ts.tv_sec = duration_integral;
|
786
785
|
ts.tv_nsec = floor(duration_fraction * 1000000000);
|
787
786
|
|
788
|
-
VALUE resume_value = Qnil;
|
789
787
|
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_TIMEOUT);
|
790
788
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
791
789
|
|
792
|
-
io_uring_backend_defer_submit_and_await(backend, sqe, ctx,
|
790
|
+
io_uring_backend_defer_submit_and_await(backend, sqe, ctx, resume_value);
|
793
791
|
OP_CONTEXT_RELEASE(&backend->store, ctx);
|
792
|
+
return ctx->completed;
|
793
|
+
}
|
794
|
+
|
795
|
+
VALUE Backend_sleep(VALUE self, VALUE duration) {
|
796
|
+
Backend_t *backend;
|
797
|
+
GetBackend(self, backend);
|
798
|
+
|
799
|
+
VALUE resume_value = Qnil;
|
800
|
+
io_uring_backend_submit_timeout_and_await(backend, NUM2DBL(duration), &resume_value);
|
794
801
|
RAISE_IF_EXCEPTION(resume_value);
|
795
802
|
RB_GC_GUARD(resume_value);
|
796
803
|
return resume_value;
|
797
804
|
}
|
798
805
|
|
806
|
+
VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
807
|
+
Backend_t *backend;
|
808
|
+
double interval_d = NUM2DBL(interval);
|
809
|
+
GetBackend(self, backend);
|
810
|
+
double next_time = 0.;
|
811
|
+
|
812
|
+
while (1) {
|
813
|
+
double now = current_time();
|
814
|
+
if (next_time == 0.) next_time = current_time() + interval_d;
|
815
|
+
double sleep_duration = next_time - now;
|
816
|
+
if (sleep_duration < 0) sleep_duration = 0;
|
817
|
+
|
818
|
+
VALUE resume_value = Qnil;
|
819
|
+
int completed = io_uring_backend_submit_timeout_and_await(backend, sleep_duration, &resume_value);
|
820
|
+
RAISE_IF_EXCEPTION(resume_value);
|
821
|
+
if (!completed) return resume_value;
|
822
|
+
RB_GC_GUARD(resume_value);
|
823
|
+
|
824
|
+
rb_yield(Qnil);
|
825
|
+
|
826
|
+
while (1) {
|
827
|
+
next_time += interval_d;
|
828
|
+
if (next_time > now) break;
|
829
|
+
}
|
830
|
+
}
|
831
|
+
}
|
832
|
+
|
799
833
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
800
834
|
Backend_t *backend;
|
801
835
|
int pid_int = NUM2INT(pid);
|
@@ -864,6 +898,7 @@ void Init_Backend() {
|
|
864
898
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
865
899
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
866
900
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
901
|
+
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
867
902
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
868
903
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
869
904
|
|
@@ -7,6 +7,7 @@
|
|
7
7
|
#include <fcntl.h>
|
8
8
|
#include <netinet/in.h>
|
9
9
|
#include <arpa/inet.h>
|
10
|
+
#include <stdnoreturn.h>
|
10
11
|
|
11
12
|
#include "polyphony.h"
|
12
13
|
#include "../libev/ev.h"
|
@@ -688,6 +689,39 @@ VALUE Backend_sleep(VALUE self, VALUE duration) {
|
|
688
689
|
return switchpoint_result;
|
689
690
|
}
|
690
691
|
|
692
|
+
noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
693
|
+
Backend_t *backend;
|
694
|
+
struct libev_timer watcher;
|
695
|
+
double interval_d = NUM2DBL(interval);
|
696
|
+
|
697
|
+
GetBackend(self, backend);
|
698
|
+
watcher.fiber = rb_fiber_current();
|
699
|
+
|
700
|
+
double next_time = 0.;
|
701
|
+
|
702
|
+
while (1) {
|
703
|
+
double now = current_time();
|
704
|
+
if (next_time == 0.) next_time = current_time() + interval_d;
|
705
|
+
double sleep_duration = next_time - now;
|
706
|
+
if (sleep_duration < 0) sleep_duration = 0;
|
707
|
+
|
708
|
+
VALUE switchpoint_result = Qnil;
|
709
|
+
ev_timer_init(&watcher.timer, Backend_timer_callback, sleep_duration, 0.);
|
710
|
+
ev_timer_start(backend->ev_loop, &watcher.timer);
|
711
|
+
switchpoint_result = backend_await(backend);
|
712
|
+
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
713
|
+
RAISE_IF_EXCEPTION(switchpoint_result);
|
714
|
+
RB_GC_GUARD(switchpoint_result);
|
715
|
+
|
716
|
+
rb_yield(Qnil);
|
717
|
+
|
718
|
+
while (1) {
|
719
|
+
next_time += interval_d;
|
720
|
+
if (next_time > now) break;
|
721
|
+
}
|
722
|
+
}
|
723
|
+
}
|
724
|
+
|
691
725
|
struct libev_child {
|
692
726
|
struct ev_child child;
|
693
727
|
VALUE fiber;
|
@@ -777,6 +811,7 @@ void Init_Backend() {
|
|
777
811
|
rb_define_method(cBackend, "send", Backend_write, 2);
|
778
812
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
779
813
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
814
|
+
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
780
815
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
781
816
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
782
817
|
|
data/ext/polyphony/fiber.c
CHANGED
@@ -21,7 +21,7 @@ VALUE SYM_fiber_terminate;
|
|
21
21
|
|
22
22
|
static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
|
23
23
|
VALUE arg = (argc == 0) ? Qnil : argv[0];
|
24
|
-
VALUE ret =
|
24
|
+
VALUE ret = FIBER_TRANSFER(self, arg);
|
25
25
|
|
26
26
|
RAISE_IF_EXCEPTION(ret);
|
27
27
|
RB_GC_GUARD(ret);
|
@@ -42,10 +42,6 @@ inline VALUE Fiber_auto_watcher(VALUE self) {
|
|
42
42
|
void Fiber_make_runnable(VALUE fiber, VALUE value) {
|
43
43
|
VALUE thread = rb_ivar_get(fiber, ID_ivar_thread);
|
44
44
|
if (thread == Qnil) {
|
45
|
-
INSPECT("Fiber with no thread", fiber);
|
46
|
-
TRACE_CALLER();
|
47
|
-
TRACE_C_STACK();
|
48
|
-
exit(-1);
|
49
45
|
rb_raise(rb_eRuntimeError, "No thread set for fiber");
|
50
46
|
// rb_warn("No thread set for fiber");
|
51
47
|
return;
|
@@ -57,7 +53,6 @@ void Fiber_make_runnable(VALUE fiber, VALUE value) {
|
|
57
53
|
void Fiber_make_runnable_with_priority(VALUE fiber, VALUE value) {
|
58
54
|
VALUE thread = rb_ivar_get(fiber, ID_ivar_thread);
|
59
55
|
if (thread == Qnil) {
|
60
|
-
INSPECT("Fiber with no thread", fiber);
|
61
56
|
rb_raise(rb_eRuntimeError, "No thread set for fiber");
|
62
57
|
// rb_warn("No thread set for fiber");
|
63
58
|
return;
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -23,12 +23,15 @@
|
|
23
23
|
#define TRACE(...) rb_funcall(rb_cObject, ID_fiber_trace, __VA_ARGS__)
|
24
24
|
#define COND_TRACE(...) if (__tracing_enabled__) { TRACE(__VA_ARGS__); }
|
25
25
|
|
26
|
+
// exceptions
|
26
27
|
#define TEST_EXCEPTION(ret) (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
|
27
|
-
|
28
28
|
#define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
|
29
29
|
#define RAISE_IF_EXCEPTION(ret) if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) { RAISE_EXCEPTION(ret); }
|
30
30
|
#define RAISE_IF_NOT_NIL(ret) if (ret != Qnil) { RAISE_EXCEPTION(ret); }
|
31
31
|
|
32
|
+
// Fiber#transfer
|
33
|
+
#define FIBER_TRANSFER(fiber, value) rb_funcall(fiber, ID_transfer, 1, value)
|
34
|
+
|
32
35
|
extern backend_interface_t backend_interface;
|
33
36
|
#define __BACKEND__ (backend_interface)
|
34
37
|
|
data/ext/polyphony/thread.c
CHANGED
@@ -4,7 +4,6 @@ ID ID_deactivate_all_watchers_post_fork;
|
|
4
4
|
ID ID_ivar_backend;
|
5
5
|
ID ID_ivar_join_wait_queue;
|
6
6
|
ID ID_ivar_main_fiber;
|
7
|
-
ID ID_ivar_result;
|
8
7
|
ID ID_ivar_terminated;
|
9
8
|
ID ID_ivar_runqueue;
|
10
9
|
ID ID_stop;
|
@@ -116,7 +115,7 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
116
115
|
RB_GC_GUARD(next.fiber);
|
117
116
|
RB_GC_GUARD(next.value);
|
118
117
|
return (next.fiber == current_fiber) ?
|
119
|
-
next.value :
|
118
|
+
next.value : FIBER_TRANSFER(next.fiber, next.value);
|
120
119
|
}
|
121
120
|
|
122
121
|
VALUE Thread_reset_fiber_scheduling(VALUE self) {
|
@@ -162,7 +161,6 @@ void Init_Thread() {
|
|
162
161
|
ID_ivar_backend = rb_intern("@backend");
|
163
162
|
ID_ivar_join_wait_queue = rb_intern("@join_wait_queue");
|
164
163
|
ID_ivar_main_fiber = rb_intern("@main_fiber");
|
165
|
-
ID_ivar_result = rb_intern("@result");
|
166
164
|
ID_ivar_terminated = rb_intern("@terminated");
|
167
165
|
ID_ivar_runqueue = rb_intern("@runqueue");
|
168
166
|
ID_stop = rb_intern("stop");
|
@@ -20,15 +20,20 @@ module Polyphony
|
|
20
20
|
canceller = spin do
|
21
21
|
sleep interval
|
22
22
|
exception = cancel_exception(with_exception)
|
23
|
+
# we don't want the cancelling fiber caller location as part of the
|
24
|
+
# exception backtrace
|
25
|
+
exception.__raising_fiber__ = nil
|
23
26
|
fiber.schedule exception
|
24
27
|
end
|
25
28
|
block ? cancel_after_wrap_block(canceller, &block) : canceller
|
26
29
|
end
|
27
30
|
|
28
31
|
def cancel_exception(exception)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
+
case exception
|
33
|
+
when Class then exception.new
|
34
|
+
when Array then exception[0].new(exception[1])
|
35
|
+
else RuntimeError.new(exception)
|
36
|
+
end
|
32
37
|
end
|
33
38
|
|
34
39
|
def cancel_after_wrap_block(canceller, &block)
|
@@ -12,7 +12,7 @@ class ::Exception
|
|
12
12
|
attr_accessor :__disable_sanitized_backtrace__
|
13
13
|
end
|
14
14
|
|
15
|
-
attr_accessor :source_fiber
|
15
|
+
attr_accessor :source_fiber, :__raising_fiber__
|
16
16
|
|
17
17
|
alias_method :orig_initialize, :initialize
|
18
18
|
def initialize(*args)
|
@@ -22,8 +22,8 @@ class ::Exception
|
|
22
22
|
|
23
23
|
alias_method :orig_backtrace, :backtrace
|
24
24
|
def backtrace
|
25
|
-
unless @
|
26
|
-
@
|
25
|
+
unless @backtrace_called
|
26
|
+
@backtrace_called = true
|
27
27
|
return orig_backtrace
|
28
28
|
end
|
29
29
|
|
@@ -31,12 +31,10 @@ class ::Exception
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def sanitized_backtrace
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
sanitize(orig_backtrace)
|
39
|
-
end
|
34
|
+
return sanitize(orig_backtrace) unless @__raising_fiber__
|
35
|
+
|
36
|
+
backtrace = orig_backtrace || []
|
37
|
+
sanitize(backtrace + @__raising_fiber__.caller)
|
40
38
|
end
|
41
39
|
|
42
40
|
POLYPHONY_DIR = File.expand_path(File.join(__dir__, '..'))
|
@@ -164,11 +162,7 @@ end
|
|
164
162
|
|
165
163
|
# Override Timeout to use cancel scope
|
166
164
|
module ::Timeout
|
167
|
-
def self.timeout(sec, klass =
|
168
|
-
cancel_after(sec, &block)
|
169
|
-
rescue Polyphony::Cancel => e
|
170
|
-
error = klass ? klass.new(message) : ::Timeout::Error.new
|
171
|
-
error.set_backtrace(e.backtrace)
|
172
|
-
raise error
|
165
|
+
def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
|
166
|
+
cancel_after(sec, with_exception: [klass, message], &block)
|
173
167
|
end
|
174
168
|
end
|
data/lib/polyphony/version.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/stress.rb
CHANGED
data/test/test_backend.rb
CHANGED
@@ -125,4 +125,15 @@ class BackendTest < MiniTest::Test
|
|
125
125
|
snooze
|
126
126
|
server&.close
|
127
127
|
end
|
128
|
+
|
129
|
+
def test_timer_loop
|
130
|
+
i = 0
|
131
|
+
f = spin do
|
132
|
+
@backend.timer_loop(0.01) { i += 1 }
|
133
|
+
end
|
134
|
+
@backend.sleep(0.05)
|
135
|
+
f.stop
|
136
|
+
f.await # TODO: check why this test sometimes segfaults if we don't a<wait fiber
|
137
|
+
assert_in_range 4..6, i
|
138
|
+
end
|
128
139
|
end
|
data/test/test_global_api.rb
CHANGED
@@ -202,6 +202,19 @@ class CancelAfterTest < MiniTest::Test
|
|
202
202
|
end
|
203
203
|
end
|
204
204
|
|
205
|
+
begin
|
206
|
+
err = nil
|
207
|
+
cancel_after(0.01, with_exception: [CustomException, 'custom message']) do
|
208
|
+
sleep 1
|
209
|
+
:foo
|
210
|
+
end
|
211
|
+
rescue Exception => err
|
212
|
+
ensure
|
213
|
+
assert_kind_of CustomException, err
|
214
|
+
assert_equal 'custom message', err.message
|
215
|
+
end
|
216
|
+
|
217
|
+
|
205
218
|
begin
|
206
219
|
e = nil
|
207
220
|
cancel_after(0.01, with_exception: 'foo') do
|
data/test/test_queue.rb
CHANGED
data/test/test_socket.rb
CHANGED
@@ -40,12 +40,12 @@ class HTTPClientTest < MiniTest::Test
|
|
40
40
|
def test_http
|
41
41
|
res = HTTParty.get('http://worldtimeapi.org/api/timezone/Europe/Paris')
|
42
42
|
response = JSON.load(res.body)
|
43
|
-
assert_equal "
|
43
|
+
assert_equal "CET", response['abbreviation']
|
44
44
|
end
|
45
45
|
|
46
46
|
def test_https
|
47
47
|
res = HTTParty.get('https://worldtimeapi.org/api/timezone/Europe/Paris')
|
48
48
|
response = JSON.load(res.body)
|
49
|
-
assert_equal "
|
49
|
+
assert_equal "CET", response['abbreviation']
|
50
50
|
end
|
51
51
|
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.46.
|
4
|
+
version: 0.46.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -290,6 +290,7 @@ files:
|
|
290
290
|
- TODO.md
|
291
291
|
- bin/polyphony-debug
|
292
292
|
- bin/stress.rb
|
293
|
+
- bin/test
|
293
294
|
- docs/_config.yml
|
294
295
|
- docs/_includes/head.html
|
295
296
|
- docs/_includes/title.html
|