polyphony 0.90 → 0.91
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 +6 -0
- data/Gemfile.lock +1 -1
- data/examples/pipes/echo_server.rb +17 -0
- data/examples/pipes/gunzip.rb +6 -0
- data/examples/pipes/gzip.rb +6 -0
- data/examples/pipes/gzip_http_server.rb +49 -0
- data/examples/pipes/tcp_proxy.rb +28 -0
- data/examples/pipes/tee.rb +15 -0
- data/ext/polyphony/backend_common.c +9 -7
- data/ext/polyphony/backend_io_uring.c +129 -20
- data/ext/polyphony/backend_libev.c +23 -23
- data/ext/polyphony/io_extensions.c +0 -1
- data/ext/polyphony/polyphony.c +11 -1
- data/ext/polyphony/polyphony.h +7 -0
- data/ext/polyphony/queue.c +3 -3
- data/ext/polyphony/socket_extensions.c +2 -2
- data/lib/polyphony/extensions/io.rb +4 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/stress.rb +1 -1
- data/test/test_io.rb +25 -0
- data/test/test_signal.rb +6 -2
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1b4a68e893c4cdca8e308cf3297fbf2549f70c0a7038f7c492f5c7c0a6ca6b4
|
4
|
+
data.tar.gz: 65a1cd1b10fa1a29c37c24972c0a47c324f744ff0ddba6e67464000da2a2707e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 316969779f3e2ce5a055c886ee89448b1908e57dcfb06775f5aa01491e895b450cfdaa3ec3d1f72f3a59017326dd7c3478b21e85cb7914a8bf2c17544bd47de7
|
7
|
+
data.tar.gz: 0a5badc5927cac1b111a13dd65eac242e2c2a7436dbf9a42e2376c4b321d042e27012e7d6b3906bf1d434d62a85bbfa8651700f2d4585475cbf89bc52de64569
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
def handle_client(conn)
|
7
|
+
spin do
|
8
|
+
buffer = Polyphony.pipe
|
9
|
+
spin { IO.splice_to_eof(conn, buffer) }
|
10
|
+
IO.splice_to_eof(buffer, conn)
|
11
|
+
end
|
12
|
+
rescue SystemCallError
|
13
|
+
# ignore
|
14
|
+
end
|
15
|
+
|
16
|
+
puts "Serving echo on port 1234..."
|
17
|
+
TCPServer.new('127.0.0.1', 1234).accept_loop { |c| handle_client(c) }
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/inline'
|
4
|
+
|
5
|
+
gemfile do
|
6
|
+
gem 'h1p'
|
7
|
+
gem 'polyphony', path: '.'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'polyphony'
|
11
|
+
require 'h1p'
|
12
|
+
|
13
|
+
def handle_client(conn)
|
14
|
+
spin do
|
15
|
+
parser = H1P::Parser.new(conn, :server)
|
16
|
+
|
17
|
+
while true # assuming persistent connection
|
18
|
+
headers = parser.parse_headers
|
19
|
+
break unless headers
|
20
|
+
|
21
|
+
raw_buffer = Polyphony.pipe
|
22
|
+
gzip_buffer = Polyphony.pipe
|
23
|
+
|
24
|
+
# splice request body to buffer
|
25
|
+
spin do
|
26
|
+
parser.splice_body_to(raw_buffer)
|
27
|
+
raw_buffer.close
|
28
|
+
end
|
29
|
+
|
30
|
+
# zip data from buffer into gzip buffer
|
31
|
+
spin do
|
32
|
+
IO.gzip(raw_buffer, gzip_buffer)
|
33
|
+
gzip_buffer.close
|
34
|
+
end
|
35
|
+
|
36
|
+
# send headers and splice response from gzip buffer
|
37
|
+
conn << "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"
|
38
|
+
IO.http1_splice_chunked(gzip_buffer, conn, 65535)
|
39
|
+
end
|
40
|
+
rescue H1P::Error
|
41
|
+
puts 'Got invalid request, closing connection...'
|
42
|
+
ensure
|
43
|
+
conn.close
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "Serving echo on port 1234..."
|
48
|
+
TCPServer.new('127.0.0.1', 1234).accept_loop { |c| handle_client(c) }
|
49
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
DESTINATION = ['127.0.0.1', 1234]
|
7
|
+
|
8
|
+
def handle_client(conn)
|
9
|
+
spin do
|
10
|
+
dest = TCPSocket.new(*DESTINATION)
|
11
|
+
w_buffer = Polyphony.pipe
|
12
|
+
r_buffer = Polyphony.pipe
|
13
|
+
|
14
|
+
spin { IO.splice_to_eof(conn, w_buffer) }
|
15
|
+
spin { IO.splice_to_eof(w_buffer, dest) }
|
16
|
+
|
17
|
+
spin { IO.splice_to_eof(dest, r_buffer) }
|
18
|
+
spin { IO.splice_to_eof(r_buffer, conn) }
|
19
|
+
|
20
|
+
Fiber.current.await_all_children
|
21
|
+
end
|
22
|
+
rescue SystemCallError
|
23
|
+
dest.close rescue nil
|
24
|
+
# ignore
|
25
|
+
end
|
26
|
+
|
27
|
+
puts "Serving TCP proxy on port 4321..."
|
28
|
+
TCPServer.new('127.0.0.1', 4321).accept_loop { |c| handle_client(c) }
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
chunk_size = 1 << 16
|
7
|
+
file_path = ARGV[0]
|
8
|
+
|
9
|
+
File.open(file_path, 'w+') do |f|
|
10
|
+
loop do
|
11
|
+
len = IO.tee(STDIN, STDOUT, chunk_size)
|
12
|
+
break if len == 0
|
13
|
+
IO.splice(STDIN, f, len)
|
14
|
+
end
|
15
|
+
end
|
@@ -140,7 +140,9 @@ inline void backend_base_unpark_fiber(struct Backend_base *base, VALUE fiber) {
|
|
140
140
|
inline void backend_trace(struct Backend_base *base, int argc, VALUE *argv) {
|
141
141
|
if (base->trace_proc == Qnil || base->in_trace_proc) return;
|
142
142
|
|
143
|
+
base->in_trace_proc = 1;
|
143
144
|
rb_funcallv(base->trace_proc, ID_call, argc, argv);
|
145
|
+
base->in_trace_proc = 0;
|
144
146
|
}
|
145
147
|
|
146
148
|
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
@@ -416,13 +418,13 @@ VALUE Backend_stats(VALUE self) {
|
|
416
418
|
struct backend_stats backend_stats = backend_get_stats(self);
|
417
419
|
|
418
420
|
VALUE stats = rb_hash_new();
|
419
|
-
rb_hash_aset(stats, SYM_runqueue_size,
|
420
|
-
rb_hash_aset(stats, SYM_runqueue_length,
|
421
|
-
rb_hash_aset(stats, SYM_runqueue_max_length,
|
422
|
-
rb_hash_aset(stats, SYM_op_count,
|
423
|
-
rb_hash_aset(stats, SYM_switch_count,
|
424
|
-
rb_hash_aset(stats, SYM_poll_count,
|
425
|
-
rb_hash_aset(stats, SYM_pending_ops,
|
421
|
+
rb_hash_aset(stats, SYM_runqueue_size, INT2FIX(backend_stats.runqueue_size));
|
422
|
+
rb_hash_aset(stats, SYM_runqueue_length, INT2FIX(backend_stats.runqueue_length));
|
423
|
+
rb_hash_aset(stats, SYM_runqueue_max_length, INT2FIX(backend_stats.runqueue_max_length));
|
424
|
+
rb_hash_aset(stats, SYM_op_count, INT2FIX(backend_stats.op_count));
|
425
|
+
rb_hash_aset(stats, SYM_switch_count, INT2FIX(backend_stats.switch_count));
|
426
|
+
rb_hash_aset(stats, SYM_poll_count, INT2FIX(backend_stats.poll_count));
|
427
|
+
rb_hash_aset(stats, SYM_pending_ops, INT2FIX(backend_stats.pending_ops));
|
426
428
|
RB_GC_GUARD(stats);
|
427
429
|
return stats;
|
428
430
|
}
|
@@ -364,7 +364,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
364
364
|
int fd;
|
365
365
|
rb_io_t *fptr;
|
366
366
|
struct io_buffer buffer = get_io_buffer(str);
|
367
|
-
long buf_pos =
|
367
|
+
long buf_pos = FIX2INT(pos);
|
368
368
|
int shrinkable_string = 0;
|
369
369
|
int expandable_buffer = 0;
|
370
370
|
long total = 0;
|
@@ -456,7 +456,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
456
456
|
rb_io_t *fptr;
|
457
457
|
VALUE str;
|
458
458
|
long total;
|
459
|
-
long len =
|
459
|
+
long len = FIX2INT(maxlen);
|
460
460
|
int shrinkable;
|
461
461
|
char *buf;
|
462
462
|
|
@@ -584,7 +584,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
584
584
|
}
|
585
585
|
}
|
586
586
|
|
587
|
-
return
|
587
|
+
return INT2FIX(buffer.len);
|
588
588
|
}
|
589
589
|
|
590
590
|
VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
@@ -652,7 +652,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
652
652
|
}
|
653
653
|
|
654
654
|
free(iov);
|
655
|
-
return
|
655
|
+
return INT2FIX(total_written);
|
656
656
|
}
|
657
657
|
|
658
658
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
@@ -669,7 +669,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
669
669
|
int fd;
|
670
670
|
rb_io_t *fptr;
|
671
671
|
struct io_buffer buffer = get_io_buffer(str);
|
672
|
-
long buf_pos =
|
672
|
+
long buf_pos = FIX2INT(pos);
|
673
673
|
int shrinkable_string = 0;
|
674
674
|
int expandable_buffer = 0;
|
675
675
|
long total = 0;
|
@@ -742,7 +742,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
742
742
|
rb_io_t *fptr;
|
743
743
|
VALUE str;
|
744
744
|
long total;
|
745
|
-
long len =
|
745
|
+
long len = FIX2INT(maxlen);
|
746
746
|
int shrinkable;
|
747
747
|
char *buf;
|
748
748
|
|
@@ -838,7 +838,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
838
838
|
|
839
839
|
struct io_buffer buffer = get_io_buffer(str);
|
840
840
|
long left = buffer.len;
|
841
|
-
int flags_int =
|
841
|
+
int flags_int = FIX2INT(flags);
|
842
842
|
|
843
843
|
GetBackend(self, backend);
|
844
844
|
fd = fd_from_io(io, &fptr, 1, 0);
|
@@ -869,7 +869,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
869
869
|
}
|
870
870
|
}
|
871
871
|
|
872
|
-
return
|
872
|
+
return INT2FIX(buffer.len);
|
873
873
|
}
|
874
874
|
|
875
875
|
VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
|
@@ -954,7 +954,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
954
954
|
int result;
|
955
955
|
int completed;
|
956
956
|
|
957
|
-
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1,
|
957
|
+
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, FIX2INT(maxlen), 0);
|
958
958
|
|
959
959
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
960
960
|
completed = context_store_release(&backend->store, ctx);
|
@@ -965,7 +965,7 @@ VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE m
|
|
965
965
|
rb_syserr_fail(-result, strerror(-result));
|
966
966
|
|
967
967
|
total += result;
|
968
|
-
if (result == 0 || !loop) return
|
968
|
+
if (result == 0 || !loop) return INT2FIX(total);
|
969
969
|
}
|
970
970
|
|
971
971
|
RB_GC_GUARD(resume_value);
|
@@ -984,6 +984,112 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize)
|
|
984
984
|
return io_uring_backend_splice(backend, src, dest, chunksize, 1);
|
985
985
|
}
|
986
986
|
|
987
|
+
struct double_splice_ctx {
|
988
|
+
Backend_t *backend;
|
989
|
+
VALUE src;
|
990
|
+
VALUE dest;
|
991
|
+
int pipefd[2];
|
992
|
+
};
|
993
|
+
|
994
|
+
#define DOUBLE_SPLICE_MAXLEN (1 << 16)
|
995
|
+
|
996
|
+
static inline op_context_t *prepare_double_splice_ctx(Backend_t *backend, int src_fd, int dest_fd) {
|
997
|
+
op_context_t *ctx = context_store_acquire(&backend->store, OP_SPLICE);
|
998
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
999
|
+
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, DOUBLE_SPLICE_MAXLEN, 0);
|
1000
|
+
io_uring_sqe_set_data(sqe, ctx);
|
1001
|
+
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
1002
|
+
backend->base.op_count += 1;
|
1003
|
+
backend->pending_sqes += 1;
|
1004
|
+
|
1005
|
+
return ctx;
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
static inline void io_uring_backend_cancel(Backend_t *backend, op_context_t *ctx) {
|
1009
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
1010
|
+
ctx->result = -ECANCELED;
|
1011
|
+
io_uring_prep_cancel(sqe, (__u64)ctx, 0);
|
1012
|
+
}
|
1013
|
+
|
1014
|
+
VALUE double_splice_to_eof_safe(struct double_splice_ctx *ctx) {
|
1015
|
+
int src_fd;
|
1016
|
+
int dest_fd;
|
1017
|
+
rb_io_t *src_fptr;
|
1018
|
+
rb_io_t *dest_fptr;
|
1019
|
+
int total = 0;
|
1020
|
+
VALUE resume_value = Qnil;
|
1021
|
+
|
1022
|
+
src_fd = fd_from_io(ctx->src, &src_fptr, 0, 0);
|
1023
|
+
dest_fd = fd_from_io(ctx->dest, &dest_fptr, 1, 0);
|
1024
|
+
|
1025
|
+
op_context_t *ctx_src = prepare_double_splice_ctx(ctx->backend, src_fd, ctx->pipefd[1]);
|
1026
|
+
op_context_t *ctx_dest = prepare_double_splice_ctx(ctx->backend, ctx->pipefd[0], dest_fd);
|
1027
|
+
|
1028
|
+
if (ctx->backend->pending_sqes >= ctx->backend->prepared_limit)
|
1029
|
+
io_uring_backend_immediate_submit(ctx->backend);
|
1030
|
+
|
1031
|
+
while (1) {
|
1032
|
+
resume_value = backend_await((struct Backend_base *)ctx->backend);
|
1033
|
+
|
1034
|
+
if ((ctx_src && ctx_src->ref_count == 2 && ctx_dest && ctx_dest->ref_count == 2) || TEST_EXCEPTION(resume_value)) {
|
1035
|
+
if (ctx_src) {
|
1036
|
+
context_store_release(&ctx->backend->store, ctx_src);
|
1037
|
+
io_uring_backend_cancel(ctx->backend, ctx_src);
|
1038
|
+
}
|
1039
|
+
if (ctx_dest) {
|
1040
|
+
context_store_release(&ctx->backend->store, ctx_dest);
|
1041
|
+
io_uring_backend_cancel(ctx->backend, ctx_dest);
|
1042
|
+
}
|
1043
|
+
io_uring_backend_immediate_submit(ctx->backend);
|
1044
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1045
|
+
return resume_value;
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
if (ctx_src && ctx_src->ref_count == 1) {
|
1049
|
+
context_store_release(&ctx->backend->store, ctx_src);
|
1050
|
+
if (ctx_src->result == 0) {
|
1051
|
+
// close write end of pipe
|
1052
|
+
close(ctx->pipefd[1]);
|
1053
|
+
ctx_src = NULL;
|
1054
|
+
}
|
1055
|
+
else {
|
1056
|
+
ctx_src = prepare_double_splice_ctx(ctx->backend, src_fd, ctx->pipefd[1]);
|
1057
|
+
}
|
1058
|
+
}
|
1059
|
+
if (ctx_dest && ctx_dest->ref_count == 1) {
|
1060
|
+
context_store_release(&ctx->backend->store, ctx_dest);
|
1061
|
+
if (ctx_dest->result == 0)
|
1062
|
+
break;
|
1063
|
+
else {
|
1064
|
+
total += ctx_dest->result;
|
1065
|
+
ctx_dest = prepare_double_splice_ctx(ctx->backend, ctx->pipefd[0], dest_fd);
|
1066
|
+
}
|
1067
|
+
}
|
1068
|
+
|
1069
|
+
if (ctx->backend->pending_sqes >= ctx->backend->prepared_limit)
|
1070
|
+
io_uring_backend_immediate_submit(ctx->backend);
|
1071
|
+
}
|
1072
|
+
RB_GC_GUARD(resume_value);
|
1073
|
+
return INT2FIX(total);
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
VALUE double_splice_to_eof_cleanup(struct double_splice_ctx *ctx) {
|
1077
|
+
if (ctx->pipefd[0]) close(ctx->pipefd[0]);
|
1078
|
+
if (ctx->pipefd[1]) close(ctx->pipefd[1]);
|
1079
|
+
return Qnil;
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
VALUE Backend_double_splice_to_eof(VALUE self, VALUE src, VALUE dest) {
|
1083
|
+
struct double_splice_ctx ctx = { NULL, src, dest, 0, 0 };
|
1084
|
+
GetBackend(self, ctx.backend);
|
1085
|
+
if (pipe(ctx.pipefd) == -1) rb_syserr_fail(errno, strerror(errno));
|
1086
|
+
|
1087
|
+
return rb_ensure(
|
1088
|
+
SAFE(double_splice_to_eof_safe), (VALUE)&ctx,
|
1089
|
+
SAFE(double_splice_to_eof_cleanup), (VALUE)&ctx
|
1090
|
+
);
|
1091
|
+
}
|
1092
|
+
|
987
1093
|
VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
988
1094
|
Backend_t *backend;
|
989
1095
|
GetBackend(self, backend);
|
@@ -1003,7 +1109,7 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1003
1109
|
int result;
|
1004
1110
|
int completed;
|
1005
1111
|
|
1006
|
-
io_uring_prep_tee(sqe, src_fd, dest_fd,
|
1112
|
+
io_uring_prep_tee(sqe, src_fd, dest_fd, FIX2INT(maxlen), 0);
|
1007
1113
|
|
1008
1114
|
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
1009
1115
|
completed = context_store_release(&backend->store, ctx);
|
@@ -1013,7 +1119,7 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1013
1119
|
if (result < 0)
|
1014
1120
|
rb_syserr_fail(-result, strerror(-result));
|
1015
1121
|
|
1016
|
-
return
|
1122
|
+
return INT2FIX(result);
|
1017
1123
|
}
|
1018
1124
|
|
1019
1125
|
RB_GC_GUARD(resume_value);
|
@@ -1222,7 +1328,7 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
1222
1328
|
}
|
1223
1329
|
|
1224
1330
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1225
|
-
int pid_int =
|
1331
|
+
int pid_int = FIX2INT(pid);
|
1226
1332
|
int fd = pidfd_open(pid_int, 0);
|
1227
1333
|
int status;
|
1228
1334
|
pid_t ret;
|
@@ -1246,7 +1352,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1246
1352
|
else
|
1247
1353
|
rb_syserr_fail(e, strerror(e));
|
1248
1354
|
}
|
1249
|
-
return rb_ary_new_from_args(2,
|
1355
|
+
return rb_ary_new_from_args(2, INT2FIX(ret), INT2FIX(WEXITSTATUS(status)));
|
1250
1356
|
}
|
1251
1357
|
|
1252
1358
|
/*
|
@@ -1324,7 +1430,7 @@ struct io_uring_sqe *Backend_chain_prepare_send(Backend_t *backend, VALUE io, VA
|
|
1324
1430
|
fd = fd_from_io(io, &fptr, 1, 0);
|
1325
1431
|
|
1326
1432
|
sqe = io_uring_backend_get_sqe(backend);
|
1327
|
-
io_uring_prep_send(sqe, fd, StringValuePtr(str), RSTRING_LEN(str),
|
1433
|
+
io_uring_prep_send(sqe, fd, StringValuePtr(str), RSTRING_LEN(str), FIX2INT(flags));
|
1328
1434
|
return sqe;
|
1329
1435
|
}
|
1330
1436
|
|
@@ -1338,7 +1444,7 @@ struct io_uring_sqe *Backend_chain_prepare_splice(Backend_t *backend, VALUE src,
|
|
1338
1444
|
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1339
1445
|
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
1340
1446
|
sqe = io_uring_backend_get_sqe(backend);
|
1341
|
-
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1,
|
1447
|
+
io_uring_prep_splice(sqe, src_fd, -1, dest_fd, -1, FIX2INT(maxlen), 0);
|
1342
1448
|
return sqe;
|
1343
1449
|
}
|
1344
1450
|
|
@@ -1434,7 +1540,7 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1434
1540
|
}
|
1435
1541
|
|
1436
1542
|
RB_GC_GUARD(resume_value);
|
1437
|
-
return
|
1543
|
+
return INT2FIX(result);
|
1438
1544
|
}
|
1439
1545
|
|
1440
1546
|
VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
|
@@ -1540,7 +1646,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1540
1646
|
src_fd = fd_from_io(src, &src_fptr, 0, 0);
|
1541
1647
|
dest_fd = fd_from_io(dest, &dest_fptr, 1, 0);
|
1542
1648
|
|
1543
|
-
maxlen =
|
1649
|
+
maxlen = FIX2INT(chunk_size);
|
1544
1650
|
|
1545
1651
|
if (pipe(pipefd) == -1) {
|
1546
1652
|
err = errno;
|
@@ -1566,7 +1672,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1566
1672
|
if (chunk_len == 0) break;
|
1567
1673
|
|
1568
1674
|
total += chunk_len;
|
1569
|
-
chunk_len_value =
|
1675
|
+
chunk_len_value = INT2FIX(chunk_len);
|
1570
1676
|
|
1571
1677
|
|
1572
1678
|
if (chunk_prefix != Qnil) {
|
@@ -1605,7 +1711,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1605
1711
|
RB_GC_GUARD(switchpoint_result);
|
1606
1712
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1607
1713
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1608
|
-
return
|
1714
|
+
return INT2FIX(total);
|
1609
1715
|
syscallerror:
|
1610
1716
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1611
1717
|
if (pipefd[1] != -1) close(pipefd[1]);
|
@@ -1693,9 +1799,12 @@ void Init_Backend() {
|
|
1693
1799
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
1694
1800
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
1695
1801
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
1802
|
+
|
1696
1803
|
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1697
1804
|
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
1805
|
+
rb_define_method(cBackend, "double_splice_to_eof", Backend_double_splice_to_eof, 2);
|
1698
1806
|
rb_define_method(cBackend, "tee", Backend_tee, 3);
|
1807
|
+
|
1699
1808
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
1700
1809
|
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
1701
1810
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
@@ -291,7 +291,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof,
|
|
291
291
|
rb_io_t *fptr;
|
292
292
|
|
293
293
|
struct io_buffer buffer = get_io_buffer(str);
|
294
|
-
long buf_pos =
|
294
|
+
long buf_pos = FIX2INT(pos);
|
295
295
|
int shrinkable_string = 0;
|
296
296
|
int expandable_buffer = 0;
|
297
297
|
long total = 0;
|
@@ -389,7 +389,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
389
389
|
rb_io_t *fptr;
|
390
390
|
VALUE str;
|
391
391
|
long total;
|
392
|
-
long len =
|
392
|
+
long len = FIX2INT(maxlen);
|
393
393
|
int shrinkable;
|
394
394
|
char *buf;
|
395
395
|
VALUE switchpoint_result = Qnil;
|
@@ -519,7 +519,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
519
519
|
RB_GC_GUARD(watcher.fiber);
|
520
520
|
RB_GC_GUARD(switchpoint_result);
|
521
521
|
|
522
|
-
return
|
522
|
+
return INT2FIX(buffer.len);
|
523
523
|
error:
|
524
524
|
return RAISE_EXCEPTION(switchpoint_result);
|
525
525
|
}
|
@@ -590,7 +590,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
590
590
|
RB_GC_GUARD(switchpoint_result);
|
591
591
|
|
592
592
|
free(iov);
|
593
|
-
return
|
593
|
+
return INT2FIX(total_written);
|
594
594
|
error:
|
595
595
|
free(iov);
|
596
596
|
return RAISE_EXCEPTION(switchpoint_result);
|
@@ -763,7 +763,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
763
763
|
|
764
764
|
struct io_buffer buffer = get_io_buffer(str);
|
765
765
|
long left = buffer.len;
|
766
|
-
int flags_int =
|
766
|
+
int flags_int = FIX2INT(flags);
|
767
767
|
|
768
768
|
GetBackend(self, backend);
|
769
769
|
fd = fd_from_io(io, &fptr, 1, 0);
|
@@ -795,7 +795,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
795
795
|
RB_GC_GUARD(watcher.fiber);
|
796
796
|
RB_GC_GUARD(switchpoint_result);
|
797
797
|
|
798
|
-
return
|
798
|
+
return INT2FIX(buffer.len);
|
799
799
|
error:
|
800
800
|
return RAISE_EXCEPTION(switchpoint_result);
|
801
801
|
}
|
@@ -868,7 +868,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
868
868
|
|
869
869
|
while (1) {
|
870
870
|
backend->base.op_count++;
|
871
|
-
len = splice(src_fd, 0, dest_fd, 0,
|
871
|
+
len = splice(src_fd, 0, dest_fd, 0, FIX2INT(maxlen), 0);
|
872
872
|
if (len < 0) {
|
873
873
|
int e = errno;
|
874
874
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
@@ -889,7 +889,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
889
889
|
RB_GC_GUARD(watcher.ctx.fiber);
|
890
890
|
RB_GC_GUARD(switchpoint_result);
|
891
891
|
|
892
|
-
return
|
892
|
+
return INT2FIX(len);
|
893
893
|
error:
|
894
894
|
return RAISE_EXCEPTION(switchpoint_result);
|
895
895
|
}
|
@@ -912,7 +912,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
912
912
|
|
913
913
|
while (1) {
|
914
914
|
backend->base.op_count++;
|
915
|
-
len = splice(src_fd, 0, dest_fd, 0,
|
915
|
+
len = splice(src_fd, 0, dest_fd, 0, FIX2INT(maxlen), 0);
|
916
916
|
if (len < 0) {
|
917
917
|
int e = errno;
|
918
918
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
@@ -936,7 +936,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
936
936
|
RB_GC_GUARD(watcher.ctx.fiber);
|
937
937
|
RB_GC_GUARD(switchpoint_result);
|
938
938
|
|
939
|
-
return
|
939
|
+
return INT2FIX(total);
|
940
940
|
error:
|
941
941
|
return RAISE_EXCEPTION(switchpoint_result);
|
942
942
|
}
|
@@ -958,7 +958,7 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
958
958
|
|
959
959
|
while (1) {
|
960
960
|
backend->base.op_count++;
|
961
|
-
len = tee(src_fd, dest_fd,
|
961
|
+
len = tee(src_fd, dest_fd, FIX2INT(maxlen), 0);
|
962
962
|
if (len < 0) {
|
963
963
|
int e = errno;
|
964
964
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
@@ -979,7 +979,7 @@ VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
979
979
|
RB_GC_GUARD(watcher.ctx.fiber);
|
980
980
|
RB_GC_GUARD(switchpoint_result);
|
981
981
|
|
982
|
-
return
|
982
|
+
return INT2FIX(len);
|
983
983
|
error:
|
984
984
|
return RAISE_EXCEPTION(switchpoint_result);
|
985
985
|
}
|
@@ -994,7 +994,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
994
994
|
int dest_fd;
|
995
995
|
rb_io_t *src_fptr;
|
996
996
|
rb_io_t *dest_fptr;
|
997
|
-
int len =
|
997
|
+
int len = FIX2INT(maxlen);
|
998
998
|
VALUE str = rb_str_new(0, len);
|
999
999
|
char *buf = RSTRING_PTR(str);
|
1000
1000
|
int left = 0;
|
@@ -1047,7 +1047,7 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1047
1047
|
RB_GC_GUARD(switchpoint_result);
|
1048
1048
|
RB_GC_GUARD(str);
|
1049
1049
|
|
1050
|
-
return
|
1050
|
+
return INT2FIX(total);
|
1051
1051
|
error:
|
1052
1052
|
return RAISE_EXCEPTION(switchpoint_result);
|
1053
1053
|
}
|
@@ -1060,7 +1060,7 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
1060
1060
|
int dest_fd;
|
1061
1061
|
rb_io_t *src_fptr;
|
1062
1062
|
rb_io_t *dest_fptr;
|
1063
|
-
int len =
|
1063
|
+
int len = FIX2INT(maxlen);
|
1064
1064
|
VALUE str = rb_str_new(0, len);
|
1065
1065
|
char *buf = RSTRING_PTR(str);
|
1066
1066
|
int left = 0;
|
@@ -1118,7 +1118,7 @@ done:
|
|
1118
1118
|
RB_GC_GUARD(switchpoint_result);
|
1119
1119
|
RB_GC_GUARD(str);
|
1120
1120
|
|
1121
|
-
return
|
1121
|
+
return INT2FIX(total);
|
1122
1122
|
error:
|
1123
1123
|
return RAISE_EXCEPTION(switchpoint_result);
|
1124
1124
|
}
|
@@ -1263,7 +1263,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
1263
1263
|
|
1264
1264
|
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
1265
1265
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1266
|
-
int pid_int =
|
1266
|
+
int pid_int = FIX2INT(pid);
|
1267
1267
|
int fd = pidfd_open(pid_int, 0);
|
1268
1268
|
if (fd >= 0) {
|
1269
1269
|
Backend_t *backend;
|
@@ -1286,7 +1286,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1286
1286
|
int e = errno;
|
1287
1287
|
rb_syserr_fail(e, strerror(e));
|
1288
1288
|
}
|
1289
|
-
return rb_ary_new_from_args(2,
|
1289
|
+
return rb_ary_new_from_args(2, INT2FIX(ret), INT2FIX(WEXITSTATUS(status)));
|
1290
1290
|
}
|
1291
1291
|
#else
|
1292
1292
|
struct libev_child {
|
@@ -1299,7 +1299,7 @@ void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
|
1299
1299
|
int exit_status = WEXITSTATUS(w->rstatus);
|
1300
1300
|
VALUE status;
|
1301
1301
|
|
1302
|
-
status = rb_ary_new_from_args(2,
|
1302
|
+
status = rb_ary_new_from_args(2, INT2FIX(w->rpid), INT2FIX(exit_status));
|
1303
1303
|
Fiber_make_runnable(watcher->fiber, status);
|
1304
1304
|
}
|
1305
1305
|
|
@@ -1310,7 +1310,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1310
1310
|
GetBackend(self, backend);
|
1311
1311
|
|
1312
1312
|
watcher.fiber = rb_fiber_current();
|
1313
|
-
ev_child_init(&watcher.child, Backend_child_callback,
|
1313
|
+
ev_child_init(&watcher.child, Backend_child_callback, FIX2INT(pid), 0);
|
1314
1314
|
ev_child_start(backend->ev_loop, &watcher.child);
|
1315
1315
|
backend->base.op_count++;
|
1316
1316
|
|
@@ -1491,7 +1491,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1491
1491
|
|
1492
1492
|
struct libev_rw_io watcher;
|
1493
1493
|
watcher.ctx.fiber = Qnil;
|
1494
|
-
int maxlen =
|
1494
|
+
int maxlen = FIX2INT(chunk_size);
|
1495
1495
|
VALUE str = Qnil;
|
1496
1496
|
VALUE chunk_len_value = Qnil;
|
1497
1497
|
|
@@ -1515,7 +1515,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1515
1515
|
if (chunk_len == 0) break;
|
1516
1516
|
|
1517
1517
|
total += chunk_len;
|
1518
|
-
chunk_len_value =
|
1518
|
+
chunk_len_value = INT2FIX(chunk_len);
|
1519
1519
|
|
1520
1520
|
if (chunk_prefix != Qnil) {
|
1521
1521
|
VALUE str = (TYPE(chunk_prefix) == T_STRING) ? chunk_prefix : rb_funcall(chunk_prefix, ID_call, 1, chunk_len_value);
|
@@ -1553,7 +1553,7 @@ VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VAL
|
|
1553
1553
|
RB_GC_GUARD(result);
|
1554
1554
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1555
1555
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1556
|
-
return
|
1556
|
+
return INT2FIX(total);
|
1557
1557
|
syscallerror:
|
1558
1558
|
if (pipefd[0] != -1) close(pipefd[0]);
|
1559
1559
|
if (pipefd[1] != -1) close(pipefd[1]);
|
@@ -502,7 +502,6 @@ static inline VALUE z_stream_cleanup(struct z_stream_ctx *ctx) {
|
|
502
502
|
return Qnil;
|
503
503
|
}
|
504
504
|
|
505
|
-
#define SAFE(f) (VALUE (*)(VALUE))(f)
|
506
505
|
#define Z_STREAM_SAFE_IO_LOOP_WITH_CLEANUP(ctx) \
|
507
506
|
rb_ensure(SAFE(z_stream_io_loop), (VALUE)&ctx, SAFE(z_stream_cleanup), (VALUE)&ctx)
|
508
507
|
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -94,6 +94,12 @@ VALUE Polyphony_backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE c
|
|
94
94
|
return Backend_splice_to_eof(BACKEND(), src, dest, chunksize);
|
95
95
|
}
|
96
96
|
|
97
|
+
#ifdef POLYPHONY_BACKEND_LIBURING
|
98
|
+
VALUE Polyphony_backend_double_splice_to_eof(VALUE self, VALUE src, VALUE dest) {
|
99
|
+
return Backend_double_splice_to_eof(BACKEND(), src, dest);
|
100
|
+
}
|
101
|
+
#endif
|
102
|
+
|
97
103
|
#ifdef POLYPHONY_LINUX
|
98
104
|
VALUE Polyphony_backend_tee(VALUE self, VALUE src, VALUE dest, VALUE chunksize) {
|
99
105
|
return Backend_tee(BACKEND(), src, dest, chunksize);
|
@@ -126,7 +132,7 @@ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
|
|
126
132
|
|
127
133
|
VALUE Polyphony_with_raw_buffer(VALUE self, VALUE size) {
|
128
134
|
struct raw_buffer buffer;
|
129
|
-
buffer.len =
|
135
|
+
buffer.len = FIX2INT(size);
|
130
136
|
buffer.ptr = malloc(buffer.len);
|
131
137
|
if (!buffer.ptr)
|
132
138
|
rb_raise(rb_eRuntimeError, "Failed to allocate buffer");
|
@@ -187,6 +193,10 @@ void Init_Polyphony() {
|
|
187
193
|
rb_define_singleton_method(mPolyphony, "backend_splice", Polyphony_backend_splice, 3);
|
188
194
|
rb_define_singleton_method(mPolyphony, "backend_splice_to_eof", Polyphony_backend_splice_to_eof, 3);
|
189
195
|
|
196
|
+
#ifdef POLYPHONY_BACKEND_LIBURING
|
197
|
+
rb_define_singleton_method(mPolyphony, "backend_double_splice_to_eof", Polyphony_backend_double_splice_to_eof, 2);
|
198
|
+
#endif
|
199
|
+
|
190
200
|
#ifdef POLYPHONY_LINUX
|
191
201
|
rb_define_singleton_method(mPolyphony, "backend_tee", Polyphony_backend_tee, 3);
|
192
202
|
#endif
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -35,6 +35,9 @@
|
|
35
35
|
|
36
36
|
#define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
|
37
37
|
|
38
|
+
// SAFE is used to cast functions used in rb_ensure
|
39
|
+
#define SAFE(f) (VALUE (*)(VALUE))(f)
|
40
|
+
|
38
41
|
extern VALUE mPolyphony;
|
39
42
|
extern VALUE cPipe;
|
40
43
|
extern VALUE cQueue;
|
@@ -114,6 +117,10 @@ VALUE Backend_sleep(VALUE self, VALUE duration);
|
|
114
117
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
115
118
|
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize);
|
116
119
|
|
120
|
+
#ifdef POLYPHONY_BACKEND_LIBURING
|
121
|
+
VALUE Backend_double_splice_to_eof(VALUE self, VALUE src, VALUE dest);
|
122
|
+
#endif
|
123
|
+
|
117
124
|
#ifdef POLYPHONY_LINUX
|
118
125
|
VALUE Backend_tee(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
119
126
|
#endif
|
data/ext/polyphony/queue.c
CHANGED
@@ -210,7 +210,7 @@ VALUE Queue_capped_p(VALUE self) {
|
|
210
210
|
Queue_t *queue;
|
211
211
|
GetQueue(self, queue);
|
212
212
|
|
213
|
-
return queue->capacity ?
|
213
|
+
return queue->capacity ? INT2FIX(queue->capacity) : Qnil;
|
214
214
|
}
|
215
215
|
|
216
216
|
VALUE Queue_clear(VALUE self) {
|
@@ -280,14 +280,14 @@ VALUE Queue_num_waiting(VALUE self) {
|
|
280
280
|
Queue_t *queue;
|
281
281
|
GetQueue(self, queue);
|
282
282
|
|
283
|
-
return
|
283
|
+
return INT2FIX(queue->shift_queue.count);
|
284
284
|
}
|
285
285
|
|
286
286
|
VALUE Queue_size_m(VALUE self) {
|
287
287
|
Queue_t *queue;
|
288
288
|
GetQueue(self, queue);
|
289
289
|
|
290
|
-
return
|
290
|
+
return INT2FIX(queue->values.count);
|
291
291
|
}
|
292
292
|
|
293
293
|
VALUE Queue_closed_p(VALUE self) {
|
@@ -6,13 +6,13 @@ VALUE Socket_send(VALUE self, VALUE msg, VALUE flags) {
|
|
6
6
|
|
7
7
|
VALUE Socket_write(int argc, VALUE *argv, VALUE self) {
|
8
8
|
VALUE ary = rb_ary_new_from_values(argc, argv);
|
9
|
-
VALUE result = Backend_sendv(BACKEND(), self, ary,
|
9
|
+
VALUE result = Backend_sendv(BACKEND(), self, ary, INT2FIX(0));
|
10
10
|
RB_GC_GUARD(ary);
|
11
11
|
return result;
|
12
12
|
}
|
13
13
|
|
14
14
|
VALUE Socket_double_chevron(VALUE self, VALUE msg) {
|
15
|
-
Backend_send(BACKEND(), self, msg,
|
15
|
+
Backend_send(BACKEND(), self, msg, INT2FIX(0));
|
16
16
|
return self;
|
17
17
|
}
|
18
18
|
|
data/lib/polyphony/version.rb
CHANGED
data/test/stress.rb
CHANGED
data/test/test_io.rb
CHANGED
@@ -368,6 +368,31 @@ class IOTest < MiniTest::Test
|
|
368
368
|
end
|
369
369
|
end
|
370
370
|
|
371
|
+
def test_double_splice_to_eof
|
372
|
+
if Thread.current.backend.kind == :io_uring
|
373
|
+
skip "IO.double_splice_to_eof available only with io_uring"
|
374
|
+
end
|
375
|
+
|
376
|
+
src = Polyphony.pipe
|
377
|
+
dest = Polyphony.pipe
|
378
|
+
ret = nil
|
379
|
+
data = 'foobar' * 10
|
380
|
+
|
381
|
+
f1 = spin {
|
382
|
+
ret = IO.double_splice_to_eof(src, dest)
|
383
|
+
dest.close
|
384
|
+
}
|
385
|
+
|
386
|
+
src << data
|
387
|
+
src.close
|
388
|
+
|
389
|
+
f1.await
|
390
|
+
|
391
|
+
spliced = dest.read
|
392
|
+
assert_equal data, spliced
|
393
|
+
assert_equal data.bytesize, ret
|
394
|
+
end
|
395
|
+
|
371
396
|
def test_tee_from
|
372
397
|
skip "tested only on Linux" unless RUBY_PLATFORM =~ /linux/
|
373
398
|
|
data/test/test_signal.rb
CHANGED
@@ -32,11 +32,15 @@ class SignalTrapTest < Minitest::Test
|
|
32
32
|
trap ('SIGINT') { raise Interrupt }
|
33
33
|
end
|
34
34
|
|
35
|
+
# remove [:spin, :oob], [:schedule, :oob], since they are generated inside
|
36
|
+
# the signal handler, which occur while the trace proc is running.
|
37
|
+
events = events.reject do |e|
|
38
|
+
e == [:spin, :oob] || e == [:schedule, :oob]
|
39
|
+
end
|
40
|
+
|
35
41
|
expected = [
|
36
42
|
[:block, :main],
|
37
43
|
[:enter_poll, :main],
|
38
|
-
[:spin, :oob],
|
39
|
-
[:schedule, :oob],
|
40
44
|
[:leave_poll, :main],
|
41
45
|
[:unblock, :oob],
|
42
46
|
[:terminate, :oob],
|
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.91'
|
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-03-
|
11
|
+
date: 2022-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -305,6 +305,12 @@ files:
|
|
305
305
|
- examples/performance/thread-vs-fiber/threaded_server.rb
|
306
306
|
- examples/performance/thread_pool_perf.rb
|
307
307
|
- examples/performance/thread_switch.rb
|
308
|
+
- examples/pipes/echo_server.rb
|
309
|
+
- examples/pipes/gunzip.rb
|
310
|
+
- examples/pipes/gzip.rb
|
311
|
+
- examples/pipes/gzip_http_server.rb
|
312
|
+
- examples/pipes/tcp_proxy.rb
|
313
|
+
- examples/pipes/tee.rb
|
308
314
|
- ext/libev/Changes
|
309
315
|
- ext/libev/LICENSE
|
310
316
|
- ext/libev/README
|