polyphony 1.4 → 1.5
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 +8 -0
- data/TODO.md +5 -10
- data/examples/pipes/http_server.rb +42 -12
- data/examples/pipes/http_server2.rb +45 -0
- data/ext/polyphony/backend_common.h +5 -0
- data/ext/polyphony/backend_io_uring.c +140 -120
- data/ext/polyphony/backend_libev.c +43 -16
- data/ext/polyphony/extconf.rb +6 -2
- data/ext/polyphony/pipe.c +1 -1
- data/ext/polyphony/polyphony.c +0 -20
- data/ext/polyphony/polyphony.h +0 -5
- data/ext/polyphony/win_uio.h +18 -0
- data/lib/polyphony/extensions/socket.rb +0 -14
- data/lib/polyphony/extensions/timeout.rb +5 -1
- data/lib/polyphony/version.rb +1 -1
- data/test/test_backend.rb +4 -2
- data/test/test_ext.rb +14 -0
- data/test/test_global_api.rb +4 -4
- data/test/test_socket.rb +0 -95
- metadata +8 -6
@@ -42,21 +42,24 @@ thread.
|
|
42
42
|
#define _GNU_SOURCE 1
|
43
43
|
#endif
|
44
44
|
|
45
|
-
#include <netdb.h>
|
46
|
-
#include <sys/socket.h>
|
47
|
-
#include <sys/uio.h>
|
48
45
|
#include <unistd.h>
|
49
|
-
#include <netinet/in.h>
|
50
|
-
#include <arpa/inet.h>
|
51
46
|
#include <stdnoreturn.h>
|
52
47
|
#include <sys/types.h>
|
48
|
+
|
49
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
53
50
|
#include <sys/wait.h>
|
51
|
+
#endif
|
52
|
+
|
54
53
|
#include <fcntl.h>
|
55
54
|
|
56
55
|
#include "polyphony.h"
|
57
56
|
#include "../libev/ev.h"
|
58
57
|
#include "ruby/io.h"
|
59
58
|
|
59
|
+
#ifndef POLYPHONY_WINDOWS
|
60
|
+
#include <sys/uio.h>
|
61
|
+
#endif
|
62
|
+
|
60
63
|
#include "../libev/ev.h"
|
61
64
|
#include "backend_common.h"
|
62
65
|
|
@@ -267,21 +270,25 @@ VALUE libev_wait_fd(Backend_t *backend, int fd, int events, int raise_exception)
|
|
267
270
|
}
|
268
271
|
|
269
272
|
static inline int fd_from_io(VALUE io, rb_io_t **fptr, int write_mode, int rectify_file_pos) {
|
273
|
+
if (TYPE(io) == T_FIXNUM) {
|
274
|
+
*fptr = NULL;
|
275
|
+
return FIX2INT(io);
|
276
|
+
}
|
277
|
+
|
270
278
|
if (rb_obj_class(io) == cPipe) {
|
271
279
|
*fptr = NULL;
|
272
280
|
Pipe_verify_blocking_mode(io, Qfalse);
|
273
281
|
return Pipe_get_fd(io, write_mode);
|
274
282
|
}
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
}
|
283
|
+
|
284
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
285
|
+
if (underlying_io != Qnil) io = underlying_io;
|
286
|
+
|
287
|
+
GetOpenFile(io, *fptr);
|
288
|
+
int fd = rb_io_descriptor(io);
|
289
|
+
io_verify_blocking_mode(io, fd, Qfalse);
|
290
|
+
if (rectify_file_pos) rectify_io_file_pos(*fptr);
|
291
|
+
return fd;
|
285
292
|
}
|
286
293
|
|
287
294
|
VALUE Backend_read(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE to_eof, VALUE pos) {
|
@@ -558,6 +565,7 @@ error:
|
|
558
565
|
return RAISE_EXCEPTION(switchpoint_result);
|
559
566
|
}
|
560
567
|
|
568
|
+
#ifndef POLYPHONY_WINDOWS
|
561
569
|
VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
562
570
|
Backend_t *backend;
|
563
571
|
struct libev_io watcher;
|
@@ -629,15 +637,23 @@ error:
|
|
629
637
|
free(iov);
|
630
638
|
return RAISE_EXCEPTION(switchpoint_result);
|
631
639
|
}
|
640
|
+
#endif
|
632
641
|
|
633
642
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self) {
|
634
643
|
if (argc < 2)
|
635
644
|
// TODO: raise ArgumentError
|
636
645
|
rb_raise(rb_eRuntimeError, "(wrong number of arguments (expected 2 or more))");
|
637
646
|
|
647
|
+
#ifdef POLYPHONY_WINDOWS
|
648
|
+
int total = 0;
|
649
|
+
for (int i = 1; i < argc; i++)
|
650
|
+
total += FIX2INT(Backend_write(self, argv[0], argv[i]));
|
651
|
+
return INT2FIX(total);
|
652
|
+
#else
|
638
653
|
return (argc == 2) ?
|
639
654
|
Backend_write(self, argv[0], argv[1]) :
|
640
655
|
Backend_writev(self, argv[0], argc - 1, argv + 1);
|
656
|
+
#endif
|
641
657
|
}
|
642
658
|
|
643
659
|
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
@@ -1155,7 +1171,7 @@ VALUE Backend_close(VALUE self, VALUE io) {
|
|
1155
1171
|
RAISE_IF_EXCEPTION(resume_value);
|
1156
1172
|
RB_GC_GUARD(resume_value);
|
1157
1173
|
|
1158
|
-
fptr_finalize(fptr);
|
1174
|
+
if (fptr) fptr_finalize(fptr);
|
1159
1175
|
// fd = -1;
|
1160
1176
|
return io;
|
1161
1177
|
}
|
@@ -1317,6 +1333,7 @@ struct libev_child {
|
|
1317
1333
|
VALUE fiber;
|
1318
1334
|
};
|
1319
1335
|
|
1336
|
+
#ifndef POLYPHONY_WINDOWS
|
1320
1337
|
void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
1321
1338
|
struct libev_child *watcher = (struct libev_child *)w;
|
1322
1339
|
int exit_status = WEXITSTATUS(w->rstatus);
|
@@ -1325,8 +1342,12 @@ void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
|
1325
1342
|
status = rb_ary_new_from_args(2, INT2FIX(w->rpid), INT2FIX(exit_status));
|
1326
1343
|
Fiber_make_runnable(watcher->fiber, status);
|
1327
1344
|
}
|
1345
|
+
#endif
|
1328
1346
|
|
1329
1347
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1348
|
+
#ifdef POLYPHONY_WINDOWS
|
1349
|
+
rb_raise(rb_eStandardError, "Not implemented");
|
1350
|
+
#else
|
1330
1351
|
Backend_t *backend;
|
1331
1352
|
struct libev_child watcher;
|
1332
1353
|
VALUE switchpoint_result = Qnil;
|
@@ -1344,6 +1365,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1344
1365
|
RB_GC_GUARD(watcher.fiber);
|
1345
1366
|
RB_GC_GUARD(switchpoint_result);
|
1346
1367
|
return switchpoint_result;
|
1368
|
+
#endif
|
1347
1369
|
}
|
1348
1370
|
#endif
|
1349
1371
|
|
@@ -1497,6 +1519,7 @@ done:
|
|
1497
1519
|
#endif
|
1498
1520
|
}
|
1499
1521
|
|
1522
|
+
#ifdef POLYPHONY_LINUX
|
1500
1523
|
VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VALUE postfix, VALUE chunk_prefix, VALUE chunk_postfix, VALUE chunk_size) {
|
1501
1524
|
Backend_t *backend;
|
1502
1525
|
GetBackend(self, backend);
|
@@ -1586,6 +1609,7 @@ error:
|
|
1586
1609
|
if (pipefd[1] != -1) close(pipefd[1]);
|
1587
1610
|
return RAISE_EXCEPTION(result);
|
1588
1611
|
}
|
1612
|
+
#endif
|
1589
1613
|
|
1590
1614
|
VALUE Backend_trace(int argc, VALUE *argv, VALUE self) {
|
1591
1615
|
Backend_t *backend;
|
@@ -1651,7 +1675,10 @@ void Init_Backend(void) {
|
|
1651
1675
|
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
1652
1676
|
rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
|
1653
1677
|
rb_define_method(cBackend, "idle_proc=", Backend_idle_proc_set, 1);
|
1678
|
+
|
1679
|
+
#ifdef POLYPHONY_LINUX
|
1654
1680
|
rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
|
1681
|
+
#endif
|
1655
1682
|
|
1656
1683
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1657
1684
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
data/ext/polyphony/extconf.rb
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'mkmf'
|
5
|
+
require 'rbconfig'
|
5
6
|
|
6
7
|
dir_config 'polyphony_ext'
|
7
8
|
|
8
9
|
KERNEL_INFO_RE = /Linux (\d)\.(\d+)(?:\.)?((?:\d+\.?)*)(?:\-)?([\w\-]+)?/
|
9
10
|
def get_config
|
10
11
|
config = { linux: !!(RUBY_PLATFORM =~ /linux/) }
|
12
|
+
config[:windows] = !!(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
11
13
|
return config if !config[:linux]
|
12
14
|
|
13
15
|
kernel_info = `uname -sr`
|
@@ -17,7 +19,8 @@ def get_config
|
|
17
19
|
version, major_revision, distribution = m[1].to_i, m[2].to_i, m[4]
|
18
20
|
|
19
21
|
combined_version = version.to_i * 100 + major_revision.to_i
|
20
|
-
|
22
|
+
|
23
|
+
config[:kernel_version] = combined_version
|
21
24
|
config[:pidfd_open] = combined_version > 503
|
22
25
|
config[:multishot_recv] = combined_version >= 600
|
23
26
|
config[:multishot_recvmsg] = combined_version >= 600
|
@@ -31,7 +34,7 @@ def get_config
|
|
31
34
|
end
|
32
35
|
|
33
36
|
config = get_config
|
34
|
-
puts "Building Polyphony
|
37
|
+
puts "Building Polyphony (\n#{config.map { |(k, v)| " #{k}: #{v}\n"}.join})"
|
35
38
|
|
36
39
|
require_relative 'zlib_conf'
|
37
40
|
|
@@ -71,6 +74,7 @@ if config[:io_uring]
|
|
71
74
|
else
|
72
75
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
73
76
|
$defs << "-DPOLYPHONY_LINUX" if config[:linux]
|
77
|
+
$defs << "-DPOLYPHONY_WINDOWS" if config[:windows]
|
74
78
|
|
75
79
|
$defs << "-DEV_STANDALONE" # prevent libev from assuming "config.h" exists
|
76
80
|
|
data/ext/polyphony/pipe.c
CHANGED
@@ -97,8 +97,8 @@ VALUE Pipe_close(VALUE self) {
|
|
97
97
|
if (pipe->w_closed)
|
98
98
|
rb_raise(rb_eRuntimeError, "Pipe is already closed for writing");
|
99
99
|
|
100
|
+
Backend_close(BACKEND(), INT2FIX(pipe->fds[1]));
|
100
101
|
pipe->w_closed = 1;
|
101
|
-
close(pipe->fds[1]);
|
102
102
|
return self;
|
103
103
|
}
|
104
104
|
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -80,20 +80,6 @@ VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socke
|
|
80
80
|
return Backend_accept_loop(BACKEND(), server_socket, socket_class);
|
81
81
|
}
|
82
82
|
|
83
|
-
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
84
|
-
/* Starts a multishot accept operation on the given server socket. This API is
|
85
|
-
* available only for the io_uring backend.
|
86
|
-
*
|
87
|
-
* @param server_socket [Socket] socket to accept on
|
88
|
-
* @return [any] block return value
|
89
|
-
*/
|
90
|
-
|
91
|
-
VALUE Polyphony_backend_multishot_accept(VALUE self, VALUE server_socket) {
|
92
|
-
return Backend_multishot_accept(BACKEND(), server_socket);
|
93
|
-
}
|
94
|
-
#endif
|
95
|
-
|
96
|
-
|
97
83
|
/* Connects the given socket to the given address and port.
|
98
84
|
*
|
99
85
|
* @param io [Socket] socket to connect
|
@@ -433,12 +419,6 @@ void Init_Polyphony(void) {
|
|
433
419
|
rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
|
434
420
|
rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
|
435
421
|
rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
|
436
|
-
|
437
|
-
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
438
|
-
rb_define_singleton_method(mPolyphony, "backend_multishot_accept", Polyphony_backend_multishot_accept, 1);
|
439
|
-
#endif
|
440
|
-
|
441
|
-
|
442
422
|
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
|
443
423
|
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
|
444
424
|
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -101,11 +101,6 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
101
101
|
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
|
102
102
|
VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
|
103
103
|
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
104
|
-
|
105
|
-
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
106
|
-
VALUE Backend_multishot_accept(VALUE self, VALUE io);
|
107
|
-
#endif
|
108
|
-
|
109
104
|
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos);
|
110
105
|
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen);
|
111
106
|
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos);
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// source: https://stackoverflow.com/questions/57897314/fatal-error-when-compiling-include-sys-uio-h-on-project-windows
|
2
|
+
|
3
|
+
#ifndef SYS_UIO_H
|
4
|
+
#define SYS_UIO_H
|
5
|
+
|
6
|
+
#include <inttypes.h>
|
7
|
+
#include <unistd.h>
|
8
|
+
|
9
|
+
struct iovec
|
10
|
+
{
|
11
|
+
void *iov_base; /* Base address of a memory region for input or output */
|
12
|
+
size_t iov_len; /* The size of the memory pointed to by iov_base */
|
13
|
+
};
|
14
|
+
|
15
|
+
ssize_t readv(int fildes, const struct iovec *iov, int iovcnt);
|
16
|
+
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt);
|
17
|
+
|
18
|
+
#endif /* SYS_UIO_H */
|
@@ -464,20 +464,6 @@ class ::TCPServer < ::TCPSocket
|
|
464
464
|
Polyphony.backend_accept(@io, TCPSocket)
|
465
465
|
end
|
466
466
|
|
467
|
-
if Polyphony.instance_methods(false).include?(:backend_multishot_accept)
|
468
|
-
# Starts a multishot accept operation (only available with io_uring
|
469
|
-
# backend). Example usage:
|
470
|
-
#
|
471
|
-
# server.multishot_accept do
|
472
|
-
# server.accept_loop { |c| handle_connection(c) }
|
473
|
-
# end
|
474
|
-
#
|
475
|
-
# @return [any] return value of code block
|
476
|
-
def multishot_accept(&block)
|
477
|
-
Polyphony.backend_multishot_accept(@io, &block)
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
467
|
# Accepts incoming connections in an infinite loop.
|
482
468
|
#
|
483
469
|
# @yield [TCPSocket] accepted socket
|
@@ -14,6 +14,10 @@ module ::Timeout
|
|
14
14
|
# @param message [String] exception message
|
15
15
|
# @return [any] block's return value
|
16
16
|
def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
|
17
|
-
|
17
|
+
if sec.nil? || sec == 0
|
18
|
+
block.call
|
19
|
+
else
|
20
|
+
cancel_after(sec, with_exception: [klass, message], &block)
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
data/lib/polyphony/version.rb
CHANGED
data/test/test_backend.rb
CHANGED
@@ -317,6 +317,8 @@ class BackendTest < MiniTest::Test
|
|
317
317
|
end
|
318
318
|
|
319
319
|
def test_splice_chunks
|
320
|
+
skip if !Thread.current.backend.respond_to?(:splice_chunks)
|
321
|
+
|
320
322
|
body = 'abcd' * 4
|
321
323
|
chunk_size = 12
|
322
324
|
|
@@ -346,8 +348,8 @@ class BackendTest < MiniTest::Test
|
|
346
348
|
expected = "Content-Type: foo\r\n\r\n#{12.to_s(16)}\r\n#{body[0..11]}\r\n#{4.to_s(16)}\r\n#{body[12..15]}\r\n0\r\n\r\n"
|
347
349
|
assert_equal expected, buf
|
348
350
|
ensure
|
349
|
-
o
|
350
|
-
w
|
351
|
+
o&.close
|
352
|
+
w&.close
|
351
353
|
end
|
352
354
|
|
353
355
|
def test_idle_gc
|
data/test/test_ext.rb
CHANGED
@@ -242,6 +242,20 @@ class TimeoutTest < MiniTest::Test
|
|
242
242
|
assert_equal [0, 1, 2], buffer
|
243
243
|
end
|
244
244
|
|
245
|
+
def test_timeout_with_nil_or_zero
|
246
|
+
v = Timeout.timeout(nil) do
|
247
|
+
sleep 0.01
|
248
|
+
:foo
|
249
|
+
end
|
250
|
+
assert_equal :foo, v
|
251
|
+
|
252
|
+
v = Timeout.timeout(0) do
|
253
|
+
sleep 0.01
|
254
|
+
:bar
|
255
|
+
end
|
256
|
+
assert_equal :bar, v
|
257
|
+
end
|
258
|
+
|
245
259
|
class MyTimeout < Exception
|
246
260
|
end
|
247
261
|
|
data/test/test_global_api.rb
CHANGED
@@ -128,16 +128,16 @@ class MoveOnAfterTest < MiniTest::Test
|
|
128
128
|
|
129
129
|
def test_move_on_after_with_reset
|
130
130
|
t0 = monotonic_clock
|
131
|
-
v = move_on_after(0.
|
132
|
-
sleep 0.
|
131
|
+
v = move_on_after(0.1, with_value: :moved_on) do |timeout|
|
132
|
+
sleep 0.06
|
133
133
|
timeout.reset
|
134
|
-
sleep 0.
|
134
|
+
sleep 0.06
|
135
135
|
nil
|
136
136
|
end
|
137
137
|
t1 = monotonic_clock
|
138
138
|
|
139
139
|
assert_nil v
|
140
|
-
assert_in_range 0.
|
140
|
+
assert_in_range 0.12..0.30, t1 - t0 if IS_LINUX
|
141
141
|
end
|
142
142
|
|
143
143
|
def test_nested_move_on_after
|
data/test/test_socket.rb
CHANGED
@@ -390,98 +390,3 @@ class SSLSocketTest < MiniTest::Test
|
|
390
390
|
assert_kind_of OpenSSL::SSL::SSLError, errors.first
|
391
391
|
end
|
392
392
|
end
|
393
|
-
|
394
|
-
class MultishotAcceptTest < MiniTest::Test
|
395
|
-
def setup
|
396
|
-
skip if !TCPServer.instance_methods(false).include?(:multishot_accept)
|
397
|
-
end
|
398
|
-
|
399
|
-
def start_tcp_server_on_random_port(host = '127.0.0.1')
|
400
|
-
port = rand(1100..60000)
|
401
|
-
server = TCPServer.new(host, port)
|
402
|
-
[port, server]
|
403
|
-
rescue Errno::EADDRINUSE
|
404
|
-
retry
|
405
|
-
end
|
406
|
-
|
407
|
-
def test_multishot_accept_while_loop
|
408
|
-
port, server = start_tcp_server_on_random_port
|
409
|
-
server_fiber = spin do
|
410
|
-
server.multishot_accept do
|
411
|
-
while (socket = server.accept)
|
412
|
-
spin do
|
413
|
-
while (data = socket.gets(8192))
|
414
|
-
socket << data
|
415
|
-
end
|
416
|
-
end
|
417
|
-
end
|
418
|
-
end
|
419
|
-
end
|
420
|
-
|
421
|
-
snooze
|
422
|
-
client = TCPSocket.new('127.0.0.1', port)
|
423
|
-
client.write("1234\n")
|
424
|
-
assert_equal "1234\n", client.recv(8192)
|
425
|
-
client.close
|
426
|
-
|
427
|
-
client = TCPSocket.new('127.0.0.1', port)
|
428
|
-
client.write("5678\n")
|
429
|
-
assert_equal "5678\n", client.recv(8192)
|
430
|
-
client.close
|
431
|
-
|
432
|
-
ensure
|
433
|
-
server_fiber&.stop
|
434
|
-
server_fiber&.await
|
435
|
-
server&.close
|
436
|
-
end
|
437
|
-
|
438
|
-
def spin_client(socket)
|
439
|
-
spin do
|
440
|
-
while (data = socket.gets(8192))
|
441
|
-
socket << data
|
442
|
-
end
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
def test_multishot_accept_loop
|
447
|
-
port, server = start_tcp_server_on_random_port
|
448
|
-
server_fiber = spin do
|
449
|
-
server.multishot_accept do
|
450
|
-
server.accept_loop { |s| spin_client(s) }
|
451
|
-
end
|
452
|
-
end
|
453
|
-
|
454
|
-
snooze
|
455
|
-
client = TCPSocket.new('127.0.0.1', port)
|
456
|
-
client.write("1234\n")
|
457
|
-
assert_equal "1234\n", client.recv(8192)
|
458
|
-
client.close
|
459
|
-
|
460
|
-
client = TCPSocket.new('127.0.0.1', port)
|
461
|
-
client.write("5678\n")
|
462
|
-
assert_equal "5678\n", client.recv(8192)
|
463
|
-
client.close
|
464
|
-
|
465
|
-
ensure
|
466
|
-
server_fiber&.stop
|
467
|
-
server_fiber&.await
|
468
|
-
server&.close
|
469
|
-
end
|
470
|
-
|
471
|
-
def test_multishot_accept_error
|
472
|
-
port, server = start_tcp_server_on_random_port
|
473
|
-
error = nil
|
474
|
-
server_fiber = spin do
|
475
|
-
server.multishot_accept do
|
476
|
-
server.accept_loop { |s| spin_client(s) }
|
477
|
-
rescue SystemCallError => e
|
478
|
-
error = e
|
479
|
-
end
|
480
|
-
end
|
481
|
-
snooze
|
482
|
-
server.close
|
483
|
-
snooze
|
484
|
-
server_fiber.await
|
485
|
-
assert_kind_of Errno::EBADF, error
|
486
|
-
end
|
487
|
-
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: '1.
|
4
|
+
version: '1.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -150,7 +150,7 @@ dependencies:
|
|
150
150
|
- - '='
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: 2.10.0
|
153
|
-
description:
|
153
|
+
description:
|
154
154
|
email: sharon@noteflakes.com
|
155
155
|
executables: []
|
156
156
|
extensions:
|
@@ -312,6 +312,7 @@ files:
|
|
312
312
|
- examples/pipes/gzip.rb
|
313
313
|
- examples/pipes/gzip_http_server.rb
|
314
314
|
- examples/pipes/http_server.rb
|
315
|
+
- examples/pipes/http_server2.rb
|
315
316
|
- examples/pipes/tcp_proxy.rb
|
316
317
|
- examples/pipes/tee.rb
|
317
318
|
- ext/libev/Changes
|
@@ -356,6 +357,7 @@ files:
|
|
356
357
|
- ext/polyphony/runqueue_ring_buffer.h
|
357
358
|
- ext/polyphony/socket_extensions.c
|
358
359
|
- ext/polyphony/thread.c
|
360
|
+
- ext/polyphony/win_uio.h
|
359
361
|
- ext/polyphony/zlib_conf.rb
|
360
362
|
- ext/test_eintr.c
|
361
363
|
- lib/polyphony.rb
|
@@ -658,7 +660,7 @@ metadata:
|
|
658
660
|
source_code_uri: https://github.com/digital-fabric/polyphony
|
659
661
|
documentation_uri: https://www.rubydoc.info/gems/polyphony
|
660
662
|
changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
|
661
|
-
post_install_message:
|
663
|
+
post_install_message:
|
662
664
|
rdoc_options:
|
663
665
|
- "--title"
|
664
666
|
- polyphony
|
@@ -678,7 +680,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
678
680
|
version: '0'
|
679
681
|
requirements: []
|
680
682
|
rubygems_version: 3.4.1
|
681
|
-
signing_key:
|
683
|
+
signing_key:
|
682
684
|
specification_version: 4
|
683
685
|
summary: Fine grained concurrency for Ruby
|
684
686
|
test_files: []
|