polyphony 0.97 → 0.99
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 +13 -0
- data/examples/io/https_server_sni_2.rb +14 -8
- data/examples/io/irb.rb +1 -1
- data/ext/polyphony/backend_common.c +30 -0
- data/ext/polyphony/backend_common.h +1 -0
- data/ext/polyphony/backend_io_uring.c +125 -0
- data/ext/polyphony/backend_libev.c +135 -0
- data/ext/polyphony/extconf.rb +6 -5
- data/ext/polyphony/io_extensions.c +2 -0
- data/ext/polyphony/libev.h +0 -2
- data/ext/polyphony/polyphony.c +10 -0
- data/ext/polyphony/polyphony.h +2 -0
- data/lib/polyphony/adapters/irb.rb +0 -2
- data/lib/polyphony/core/sync.rb +53 -0
- data/lib/polyphony/extensions/io.rb +39 -14
- data/lib/polyphony/extensions/openssl.rb +1 -1
- data/lib/polyphony/extensions/socket.rb +30 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -0
- data/test/test_io.rb +14 -7
- data/test/test_socket.rb +131 -10
- data/test/test_sync.rb +42 -1
- data/test/test_thread.rb +2 -1
- data/vendor/liburing/.github/workflows/build.yml +7 -16
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +23 -1
- data/vendor/liburing/Makefile +4 -3
- data/vendor/liburing/Makefile.common +1 -0
- data/vendor/liburing/README +48 -0
- data/vendor/liburing/configure +76 -6
- data/vendor/liburing/debian/changelog +11 -0
- data/vendor/liburing/debian/control +7 -16
- data/vendor/liburing/debian/liburing-dev.manpages +3 -6
- data/vendor/liburing/debian/liburing2.install +1 -0
- data/vendor/liburing/debian/liburing2.symbols +56 -0
- data/vendor/liburing/debian/rules +15 -68
- data/vendor/liburing/examples/Makefile +4 -0
- data/vendor/liburing/examples/io_uring-close-test.c +123 -0
- data/vendor/liburing/examples/io_uring-udp.c +1 -1
- data/vendor/liburing/examples/send-zerocopy.c +315 -56
- data/vendor/liburing/examples/ucontext-cp.c +2 -17
- data/vendor/liburing/liburing-ffi.pc.in +12 -0
- data/vendor/liburing/liburing.pc.in +1 -1
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/make-debs.sh +3 -3
- data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
- data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
- data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
- data/vendor/liburing/man/io_uring_check_version.3 +72 -0
- data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
- data/vendor/liburing/man/io_uring_major_version.3 +1 -0
- data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
- data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
- data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
- data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
- data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
- data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
- data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
- data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
- data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
- data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
- data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
- data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
- data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
- data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
- data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
- data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
- data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
- data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
- data/vendor/liburing/man/io_uring_register.2 +15 -9
- data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
- data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
- data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files.3 +60 -5
- data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
- data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
- data/vendor/liburing/man/io_uring_setup.2 +31 -2
- data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
- data/vendor/liburing/src/Makefile +25 -3
- data/vendor/liburing/src/ffi.c +15 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
- data/vendor/liburing/src/include/liburing.h +190 -148
- data/vendor/liburing/src/int_flags.h +1 -0
- data/vendor/liburing/src/lib.h +5 -16
- data/vendor/liburing/src/liburing-ffi.map +172 -0
- data/vendor/liburing/src/liburing.map +11 -0
- data/vendor/liburing/src/nolibc.c +9 -2
- data/vendor/liburing/src/queue.c +2 -2
- data/vendor/liburing/src/register.c +66 -96
- data/vendor/liburing/src/setup.c +5 -4
- data/vendor/liburing/src/version.c +21 -0
- data/vendor/liburing/test/232c93d07b74.c +3 -3
- data/vendor/liburing/test/35fa71a030ca.c +3 -3
- data/vendor/liburing/test/500f9fbadef8.c +2 -0
- data/vendor/liburing/test/917257daa0fe.c +1 -1
- data/vendor/liburing/test/Makefile +27 -7
- data/vendor/liburing/test/a0908ae19763.c +2 -2
- data/vendor/liburing/test/a4c0b3decb33.c +2 -2
- data/vendor/liburing/test/accept-link.c +4 -4
- data/vendor/liburing/test/accept-reuse.c +5 -7
- data/vendor/liburing/test/accept.c +34 -31
- data/vendor/liburing/test/b19062a56726.c +1 -1
- data/vendor/liburing/test/buf-ring.c +58 -4
- data/vendor/liburing/test/ce593a6c480a.c +2 -2
- data/vendor/liburing/test/close-opath.c +2 -1
- data/vendor/liburing/test/connect.c +8 -0
- data/vendor/liburing/test/cq-overflow.c +14 -8
- data/vendor/liburing/test/d4ae271dfaae.c +1 -1
- data/vendor/liburing/test/defer-taskrun.c +64 -9
- data/vendor/liburing/test/defer.c +1 -1
- data/vendor/liburing/test/double-poll-crash.c +3 -3
- data/vendor/liburing/test/eeed8b54e0df.c +8 -3
- data/vendor/liburing/test/eploop.c +74 -0
- data/vendor/liburing/test/eventfd-ring.c +1 -1
- data/vendor/liburing/test/eventfd.c +1 -1
- data/vendor/liburing/test/evloop.c +73 -0
- data/vendor/liburing/test/exit-no-cleanup.c +1 -1
- data/vendor/liburing/test/fadvise.c +1 -1
- data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
- data/vendor/liburing/test/fd-pass.c +35 -16
- data/vendor/liburing/test/file-register.c +61 -0
- data/vendor/liburing/test/file-verify.c +2 -2
- data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
- data/vendor/liburing/test/fixed-link.c +1 -1
- data/vendor/liburing/test/fsnotify.c +118 -0
- data/vendor/liburing/test/hardlink.c +1 -1
- data/vendor/liburing/test/helpers.c +54 -2
- data/vendor/liburing/test/helpers.h +4 -0
- data/vendor/liburing/test/io-cancel.c +3 -1
- data/vendor/liburing/test/io_uring_passthrough.c +39 -8
- data/vendor/liburing/test/io_uring_setup.c +3 -80
- data/vendor/liburing/test/iopoll-overflow.c +118 -0
- data/vendor/liburing/test/iopoll.c +90 -4
- data/vendor/liburing/test/lfs-openat-write.c +7 -9
- data/vendor/liburing/test/lfs-openat.c +6 -8
- data/vendor/liburing/test/link_drain.c +31 -5
- data/vendor/liburing/test/madvise.c +1 -1
- data/vendor/liburing/test/msg-ring-flags.c +192 -0
- data/vendor/liburing/test/msg-ring-overflow.c +159 -0
- data/vendor/liburing/test/msg-ring.c +173 -13
- data/vendor/liburing/test/multicqes_drain.c +22 -19
- data/vendor/liburing/test/nvme.h +4 -3
- data/vendor/liburing/test/pipe-bug.c +95 -0
- data/vendor/liburing/test/poll-link.c +3 -3
- data/vendor/liburing/test/poll-many.c +41 -19
- data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
- data/vendor/liburing/test/poll-race-mshot.c +292 -0
- data/vendor/liburing/test/poll-race.c +105 -0
- data/vendor/liburing/test/poll.c +244 -26
- data/vendor/liburing/test/pollfree.c +5 -5
- data/vendor/liburing/test/read-before-exit.c +20 -3
- data/vendor/liburing/test/read-write.c +2 -0
- data/vendor/liburing/test/recv-multishot.c +96 -3
- data/vendor/liburing/test/reg-reg-ring.c +90 -0
- data/vendor/liburing/test/rename.c +1 -1
- data/vendor/liburing/test/ring-leak.c +0 -1
- data/vendor/liburing/test/ring-leak2.c +1 -1
- data/vendor/liburing/test/ringbuf-read.c +10 -6
- data/vendor/liburing/test/send-zerocopy.c +273 -103
- data/vendor/liburing/test/send_recv.c +7 -4
- data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
- data/vendor/liburing/test/single-issuer.c +7 -9
- data/vendor/liburing/test/skip-cqe.c +3 -4
- data/vendor/liburing/test/socket.c +0 -1
- data/vendor/liburing/test/sq-poll-dup.c +10 -3
- data/vendor/liburing/test/sq-poll-kthread.c +1 -1
- data/vendor/liburing/test/sq-poll-share.c +3 -2
- data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
- data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
- data/vendor/liburing/test/symlink.c +2 -1
- data/vendor/liburing/test/test.h +2 -1
- data/vendor/liburing/test/timeout-new.c +11 -7
- data/vendor/liburing/test/timeout.c +1 -2
- data/vendor/liburing/test/unlink.c +1 -1
- data/vendor/liburing/test/version.c +25 -0
- data/vendor/liburing/test/wakeup-hang.c +1 -1
- data/vendor/liburing/test/xattr.c +8 -4
- metadata +42 -6
- data/vendor/liburing/debian/compat +0 -1
- data/vendor/liburing/debian/liburing1-udeb.install +0 -1
- data/vendor/liburing/debian/liburing1.install +0 -1
- data/vendor/liburing/debian/liburing1.symbols +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4696bb7b13f68b379c29d5c38257e57c13aefd299f88727107e2f0f0a3c7d360
|
|
4
|
+
data.tar.gz: 94a3eeb8575d0d5fe6f143ab41351024b50c4c4cf919edec6c8155d9ead2831e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9e1798e18b0e7a35104009d6f480191f5ed5efd7dee69189d443cb57ab8ca2f8fd75105234cd60f52ecea2348a8c3d85f152aa869374ea8dfbab8895a2015b04
|
|
7
|
+
data.tar.gz: 835b2be245f60b04d5b750bcce6e679b11c671e31c3d0269aeafaa961c52c501193f67cf00f4f7cc5570cab499105d025863189767db8ae79f961a62d903b173
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 0.99 2023-03-09
|
|
2
|
+
|
|
3
|
+
- Add missing Mutex API methods (#76)
|
|
4
|
+
- Fix `IO.foreach` and `IO#each_line` (#74)
|
|
5
|
+
- Fix `SSLServer#accept_loop` (#59)
|
|
6
|
+
- Update liburing
|
|
7
|
+
|
|
8
|
+
## 0.98 2023-03-08
|
|
9
|
+
|
|
10
|
+
- Add basic support for UDP sockets
|
|
11
|
+
- Fix `IO#read` to return empty string when reading length zero
|
|
12
|
+
- Fix hang on `require 'polyphony'` in irb session
|
|
13
|
+
|
|
1
14
|
## 0.97 2023-02-28
|
|
2
15
|
|
|
3
16
|
- Fix working with IRB (#5)
|
|
@@ -27,15 +27,21 @@ server = Polyphony::Net.tcp_listen('localhost', 1234, opts)
|
|
|
27
27
|
|
|
28
28
|
puts 'Serving HTTPS on port 1234'
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
server.accept_loop do |socket|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
begin
|
|
31
|
+
server.accept_loop(false) do |socket|
|
|
32
|
+
spin do
|
|
33
|
+
while (data = socket.gets("\n", 8192))
|
|
34
|
+
if data.chomp.empty?
|
|
35
|
+
socket << "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 4\n\nfoo\n"
|
|
36
|
+
break
|
|
37
|
+
end
|
|
38
38
|
end
|
|
39
|
+
rescue OpenSSL::SSL::SSLError
|
|
40
|
+
# ignore
|
|
39
41
|
end
|
|
40
42
|
end
|
|
43
|
+
rescue => e
|
|
44
|
+
puts '*' * 40
|
|
45
|
+
p e
|
|
46
|
+
puts e.backtrace.join("\n")
|
|
41
47
|
end
|
data/examples/io/irb.rb
CHANGED
|
@@ -501,6 +501,36 @@ int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr) {
|
|
|
501
501
|
return addrinfo_result->ai_addrlen;
|
|
502
502
|
}
|
|
503
503
|
|
|
504
|
+
inline VALUE name_to_addrinfo(void *name, socklen_t len) {
|
|
505
|
+
switch(((struct sockaddr *)name)->sa_family) {
|
|
506
|
+
case AF_INET:
|
|
507
|
+
{
|
|
508
|
+
struct sockaddr_in *info = name;
|
|
509
|
+
char buf[INET_ADDRSTRLEN];
|
|
510
|
+
|
|
511
|
+
VALUE port = INT2NUM(ntohs(info->sin_port));
|
|
512
|
+
if (!inet_ntop(AF_INET, &info->sin_addr, buf, sizeof(buf)))
|
|
513
|
+
rb_raise(rb_eRuntimeError, "Failed to get AF_INET addr");
|
|
514
|
+
VALUE addr = rb_str_new_cstr(buf);
|
|
515
|
+
return rb_ary_new_from_args(4, rb_str_new_literal("AF_INET"), port, addr, addr);
|
|
516
|
+
RB_GC_GUARD(addr);
|
|
517
|
+
}
|
|
518
|
+
case AF_INET6:
|
|
519
|
+
{
|
|
520
|
+
struct sockaddr_in6 *info = name;
|
|
521
|
+
char buf[INET6_ADDRSTRLEN];
|
|
522
|
+
|
|
523
|
+
VALUE port = INT2NUM(ntohs(info->sin6_port));
|
|
524
|
+
if (!inet_ntop(AF_INET6, &info->sin6_addr, buf, sizeof(buf)))
|
|
525
|
+
rb_raise(rb_eRuntimeError, "Failed to get AF_INET addr");
|
|
526
|
+
VALUE addr = rb_str_new_cstr(buf);
|
|
527
|
+
return rb_ary_new_from_args(4, rb_str_new_literal("AF_INET6"), port, addr, addr);
|
|
528
|
+
RB_GC_GUARD(addr);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return Qnil;
|
|
532
|
+
}
|
|
533
|
+
|
|
504
534
|
inline struct backend_buffer_spec backend_get_buffer_spec(VALUE in, int rw) {
|
|
505
535
|
if (FIXNUM_P(in)) {
|
|
506
536
|
struct buffer_spec *spec = FIX2PTR(in);
|
|
@@ -148,5 +148,6 @@ void set_fd_blocking_mode(int fd, int blocking);
|
|
|
148
148
|
void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking);
|
|
149
149
|
void backend_setup_stats_symbols();
|
|
150
150
|
int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr);
|
|
151
|
+
VALUE name_to_addrinfo(void *name, socklen_t len);
|
|
151
152
|
|
|
152
153
|
#endif /* BACKEND_COMMON_H */
|
|
@@ -673,6 +673,67 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE pos)
|
|
|
673
673
|
return buffer_spec.raw ? INT2FIX(total) : buffer;
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
+
VALUE Backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
|
|
677
|
+
Backend_t *backend;
|
|
678
|
+
int fd;
|
|
679
|
+
rb_io_t *fptr;
|
|
680
|
+
struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 0);
|
|
681
|
+
long total = 0;
|
|
682
|
+
|
|
683
|
+
GetBackend(self, backend);
|
|
684
|
+
backend_prepare_read_buffer(buffer, maxlen, &buffer_spec, FIX2INT(pos));
|
|
685
|
+
fd = fd_from_io(io, &fptr, 0, 0);
|
|
686
|
+
|
|
687
|
+
char addr_buffer[64];
|
|
688
|
+
struct iovec iov;
|
|
689
|
+
struct msghdr msg;
|
|
690
|
+
|
|
691
|
+
iov.iov_base = StringValuePtr(buffer);
|
|
692
|
+
iov.iov_len = maxlen;
|
|
693
|
+
|
|
694
|
+
msg.msg_name = addr_buffer;
|
|
695
|
+
msg.msg_namelen = sizeof(addr_buffer);
|
|
696
|
+
msg.msg_iov = &iov;
|
|
697
|
+
msg.msg_iovlen = 1;
|
|
698
|
+
msg.msg_control = 0;
|
|
699
|
+
msg.msg_controllen = 0;
|
|
700
|
+
msg.msg_flags = 0;
|
|
701
|
+
|
|
702
|
+
while (1) {
|
|
703
|
+
VALUE resume_value = Qnil;
|
|
704
|
+
op_context_t *ctx = context_store_acquire(&backend->store, OP_RECV);
|
|
705
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
|
706
|
+
int result;
|
|
707
|
+
int completed;
|
|
708
|
+
|
|
709
|
+
io_uring_prep_recvmsg(sqe, fd, &msg, NUM2INT(flags));
|
|
710
|
+
|
|
711
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
|
712
|
+
completed = context_store_release(&backend->store, ctx);
|
|
713
|
+
if (!completed) {
|
|
714
|
+
context_attach_buffers(ctx, 1, &buffer);
|
|
715
|
+
RAISE_IF_EXCEPTION(resume_value);
|
|
716
|
+
return resume_value;
|
|
717
|
+
}
|
|
718
|
+
RB_GC_GUARD(resume_value);
|
|
719
|
+
|
|
720
|
+
if (result < 0)
|
|
721
|
+
rb_syserr_fail(-result, strerror(-result));
|
|
722
|
+
else {
|
|
723
|
+
total += result;
|
|
724
|
+
break;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (!total) return Qnil;
|
|
729
|
+
|
|
730
|
+
if (!buffer_spec.raw) backend_finalize_string_buffer(buffer, &buffer_spec, total, fptr);
|
|
731
|
+
VALUE addr = name_to_addrinfo(msg.msg_name, msg.msg_namelen);
|
|
732
|
+
VALUE rflags = INT2NUM(msg.msg_flags);
|
|
733
|
+
return rb_ary_new_from_args(3, buffer, addr, rflags);
|
|
734
|
+
RB_GC_GUARD(addr);
|
|
735
|
+
}
|
|
736
|
+
|
|
676
737
|
VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
677
738
|
Backend_t *backend;
|
|
678
739
|
int fd;
|
|
@@ -809,6 +870,68 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE buffer, VALUE flags) {
|
|
|
809
870
|
return INT2FIX(buffer_spec.len);
|
|
810
871
|
}
|
|
811
872
|
|
|
873
|
+
VALUE Backend_sendmsg(VALUE self, VALUE io, VALUE buffer, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
|
|
874
|
+
Backend_t *backend;
|
|
875
|
+
int fd;
|
|
876
|
+
rb_io_t *fptr;
|
|
877
|
+
|
|
878
|
+
struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 1);
|
|
879
|
+
long left = buffer_spec.len;
|
|
880
|
+
int flags_int = FIX2INT(flags);
|
|
881
|
+
|
|
882
|
+
GetBackend(self, backend);
|
|
883
|
+
fd = fd_from_io(io, &fptr, 1, 0);
|
|
884
|
+
|
|
885
|
+
struct iovec iov;
|
|
886
|
+
struct msghdr msg;
|
|
887
|
+
|
|
888
|
+
iov.iov_base = buffer_spec.ptr;
|
|
889
|
+
iov.iov_len = buffer_spec.len;
|
|
890
|
+
|
|
891
|
+
if (dest_sockaddr != Qnil) {
|
|
892
|
+
msg.msg_name = RSTRING_PTR(dest_sockaddr);
|
|
893
|
+
msg.msg_namelen = RSTRING_LEN(dest_sockaddr);
|
|
894
|
+
}
|
|
895
|
+
else {
|
|
896
|
+
msg.msg_name = 0;
|
|
897
|
+
msg.msg_namelen = 0;
|
|
898
|
+
}
|
|
899
|
+
msg.msg_iov = &iov;
|
|
900
|
+
msg.msg_iovlen = 1;
|
|
901
|
+
msg.msg_control = 0;
|
|
902
|
+
msg.msg_controllen = 0;
|
|
903
|
+
msg.msg_flags = 0;
|
|
904
|
+
|
|
905
|
+
while (left > 0) {
|
|
906
|
+
VALUE resume_value = Qnil;
|
|
907
|
+
op_context_t *ctx = context_store_acquire(&backend->store, OP_SEND);
|
|
908
|
+
struct io_uring_sqe *sqe = io_uring_backend_get_sqe(backend);
|
|
909
|
+
int result;
|
|
910
|
+
int completed;
|
|
911
|
+
|
|
912
|
+
io_uring_prep_sendmsg(sqe, fd, &msg, flags_int);
|
|
913
|
+
|
|
914
|
+
result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
|
915
|
+
completed = context_store_release(&backend->store, ctx);
|
|
916
|
+
if (!completed) {
|
|
917
|
+
context_attach_buffers(ctx, 1, &buffer);
|
|
918
|
+
RAISE_IF_EXCEPTION(resume_value);
|
|
919
|
+
return resume_value;
|
|
920
|
+
}
|
|
921
|
+
RB_GC_GUARD(resume_value);
|
|
922
|
+
|
|
923
|
+
if (result < 0)
|
|
924
|
+
rb_syserr_fail(-result, strerror(-result));
|
|
925
|
+
else {
|
|
926
|
+
iov.iov_base += result;
|
|
927
|
+
iov.iov_len -= result;
|
|
928
|
+
left -= result;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
return INT2FIX(buffer_spec.len);
|
|
933
|
+
}
|
|
934
|
+
|
|
812
935
|
VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
|
|
813
936
|
int server_fd;
|
|
814
937
|
rb_io_t *server_fptr;
|
|
@@ -1727,9 +1850,11 @@ void Init_Backend(void) {
|
|
|
1727
1850
|
rb_define_method(cBackend, "read", Backend_read, 5);
|
|
1728
1851
|
rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
|
|
1729
1852
|
rb_define_method(cBackend, "recv", Backend_recv, 4);
|
|
1853
|
+
rb_define_method(cBackend, "recvmsg", Backend_recvmsg, 7);
|
|
1730
1854
|
rb_define_method(cBackend, "recv_feed_loop", Backend_recv_feed_loop, 3);
|
|
1731
1855
|
rb_define_method(cBackend, "recv_loop", Backend_recv_loop, 2);
|
|
1732
1856
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
|
1857
|
+
rb_define_method(cBackend, "sendmsg", Backend_sendmsg, 5);
|
|
1733
1858
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
|
1734
1859
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
|
1735
1860
|
|
|
@@ -350,6 +350,72 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE pos)
|
|
|
350
350
|
return Backend_read(self, io, buffer, length, Qnil, pos);
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
+
VALUE Backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
|
|
354
|
+
Backend_t *backend;
|
|
355
|
+
struct libev_io watcher;
|
|
356
|
+
int fd;
|
|
357
|
+
rb_io_t *fptr;
|
|
358
|
+
|
|
359
|
+
struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 0);
|
|
360
|
+
long total = 0;
|
|
361
|
+
VALUE switchpoint_result = Qnil;
|
|
362
|
+
|
|
363
|
+
GetBackend(self, backend);
|
|
364
|
+
backend_prepare_read_buffer(buffer, maxlen, &buffer_spec, FIX2INT(pos));
|
|
365
|
+
fd = fd_from_io(io, &fptr, 0, 1);
|
|
366
|
+
watcher.fiber = Qnil;
|
|
367
|
+
|
|
368
|
+
char addr_buffer[64];
|
|
369
|
+
struct iovec iov;
|
|
370
|
+
struct msghdr msg;
|
|
371
|
+
|
|
372
|
+
iov.iov_base = StringValuePtr(buffer);
|
|
373
|
+
iov.iov_len = maxlen;
|
|
374
|
+
|
|
375
|
+
msg.msg_name = addr_buffer;
|
|
376
|
+
msg.msg_namelen = sizeof(addr_buffer);
|
|
377
|
+
msg.msg_iov = &iov;
|
|
378
|
+
msg.msg_iovlen = 1;
|
|
379
|
+
msg.msg_control = 0;
|
|
380
|
+
msg.msg_controllen = 0;
|
|
381
|
+
msg.msg_flags = 0;
|
|
382
|
+
|
|
383
|
+
while (1) {
|
|
384
|
+
backend->base.op_count++;
|
|
385
|
+
ssize_t result = recvmsg(fd, &msg, NUM2INT(flags));
|
|
386
|
+
if (result < 0) {
|
|
387
|
+
int e = errno;
|
|
388
|
+
if (e != EWOULDBLOCK && e != EAGAIN) rb_syserr_fail(e, strerror(e));
|
|
389
|
+
|
|
390
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_READ);
|
|
391
|
+
|
|
392
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
switchpoint_result = backend_snooze(&backend->base);
|
|
396
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
397
|
+
|
|
398
|
+
if (!result) break; // EOF
|
|
399
|
+
|
|
400
|
+
total += result;
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (!total) return Qnil;
|
|
406
|
+
|
|
407
|
+
if (!buffer_spec.raw) backend_finalize_string_buffer(buffer, &buffer_spec, total, fptr);
|
|
408
|
+
VALUE addr = name_to_addrinfo(msg.msg_name, msg.msg_namelen);
|
|
409
|
+
VALUE rflags = INT2NUM(msg.msg_flags);
|
|
410
|
+
|
|
411
|
+
return rb_ary_new_from_args(3, buffer, addr, rflags);
|
|
412
|
+
RB_GC_GUARD(addr);
|
|
413
|
+
RB_GC_GUARD(watcher.fiber);
|
|
414
|
+
RB_GC_GUARD(switchpoint_result);
|
|
415
|
+
error:
|
|
416
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
|
417
|
+
}
|
|
418
|
+
|
|
353
419
|
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
354
420
|
Backend_t *backend;
|
|
355
421
|
struct libev_io watcher;
|
|
@@ -768,6 +834,73 @@ error:
|
|
|
768
834
|
return RAISE_EXCEPTION(switchpoint_result);
|
|
769
835
|
}
|
|
770
836
|
|
|
837
|
+
VALUE Backend_sendmsg(VALUE self, VALUE io, VALUE buffer, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
|
|
838
|
+
Backend_t *backend;
|
|
839
|
+
struct libev_io watcher;
|
|
840
|
+
int fd;
|
|
841
|
+
rb_io_t *fptr;
|
|
842
|
+
VALUE switchpoint_result = Qnil;
|
|
843
|
+
|
|
844
|
+
struct backend_buffer_spec buffer_spec = backend_get_buffer_spec(buffer, 1);
|
|
845
|
+
long left = buffer_spec.len;
|
|
846
|
+
int flags_int = FIX2INT(flags);
|
|
847
|
+
|
|
848
|
+
GetBackend(self, backend);
|
|
849
|
+
fd = fd_from_io(io, &fptr, 1, 0);
|
|
850
|
+
watcher.fiber = Qnil;
|
|
851
|
+
|
|
852
|
+
struct iovec iov;
|
|
853
|
+
struct msghdr msg;
|
|
854
|
+
|
|
855
|
+
iov.iov_base = buffer_spec.ptr;
|
|
856
|
+
iov.iov_len = buffer_spec.len;
|
|
857
|
+
|
|
858
|
+
if (dest_sockaddr != Qnil) {
|
|
859
|
+
msg.msg_name = RSTRING_PTR(dest_sockaddr);
|
|
860
|
+
msg.msg_namelen = RSTRING_LEN(dest_sockaddr);
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
msg.msg_name = 0;
|
|
864
|
+
msg.msg_namelen = 0;
|
|
865
|
+
}
|
|
866
|
+
msg.msg_iov = &iov;
|
|
867
|
+
msg.msg_iovlen = 1;
|
|
868
|
+
msg.msg_control = 0;
|
|
869
|
+
msg.msg_controllen = 0;
|
|
870
|
+
msg.msg_flags = 0;
|
|
871
|
+
|
|
872
|
+
while (left > 0) {
|
|
873
|
+
backend->base.op_count++;
|
|
874
|
+
ssize_t result = sendmsg(fd, &msg, flags_int);
|
|
875
|
+
if (result < 0) {
|
|
876
|
+
int e = errno;
|
|
877
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
|
878
|
+
|
|
879
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fd, &watcher, EV_WRITE);
|
|
880
|
+
|
|
881
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
882
|
+
}
|
|
883
|
+
else {
|
|
884
|
+
iov.iov_base = (buffer_spec.ptr += result);
|
|
885
|
+
iov.iov_len -= result;
|
|
886
|
+
left -= result;
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (watcher.fiber == Qnil) {
|
|
891
|
+
switchpoint_result = backend_snooze(&backend->base);
|
|
892
|
+
|
|
893
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
RB_GC_GUARD(watcher.fiber);
|
|
897
|
+
RB_GC_GUARD(switchpoint_result);
|
|
898
|
+
|
|
899
|
+
return INT2FIX(buffer_spec.len);
|
|
900
|
+
error:
|
|
901
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
|
902
|
+
}
|
|
903
|
+
|
|
771
904
|
struct libev_rw_ctx {
|
|
772
905
|
int ref_count;
|
|
773
906
|
VALUE fiber;
|
|
@@ -1502,9 +1635,11 @@ void Init_Backend(void) {
|
|
|
1502
1635
|
rb_define_method(cBackend, "read", Backend_read, 5);
|
|
1503
1636
|
rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
|
|
1504
1637
|
rb_define_method(cBackend, "recv", Backend_recv, 4);
|
|
1638
|
+
rb_define_method(cBackend, "recvmsg", Backend_recvmsg, 7);
|
|
1505
1639
|
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 2);
|
|
1506
1640
|
rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
|
|
1507
1641
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
|
1642
|
+
rb_define_method(cBackend, "sendmsg", Backend_sendmsg, 5);
|
|
1508
1643
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
|
1509
1644
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
|
1510
1645
|
|
data/ext/polyphony/extconf.rb
CHANGED
|
@@ -55,16 +55,17 @@ if config[:io_uring]
|
|
|
55
55
|
else
|
|
56
56
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
|
57
57
|
$defs << "-DPOLYPHONY_LINUX" if config[:linux]
|
|
58
|
-
|
|
59
|
-
$defs <<
|
|
60
|
-
$defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
|
|
58
|
+
|
|
59
|
+
$defs << "-DEV_STANDALONE" # prevent libev from assuming "config.h" exists
|
|
61
60
|
$defs << '-DEV_USE_EPOLL' if have_header('sys/epoll.h')
|
|
62
61
|
$defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
|
|
62
|
+
$defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
|
|
63
|
+
$defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
|
|
63
64
|
$defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
|
|
65
|
+
$defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
|
|
66
|
+
|
|
64
67
|
$defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
|
|
65
68
|
|
|
66
|
-
$defs << "-DEV_STANDALONE" # prevent libev from assuming "config.h" exists
|
|
67
|
-
|
|
68
69
|
$CFLAGS << " -Wno-comment"
|
|
69
70
|
$CFLAGS << " -Wno-unused-result"
|
|
70
71
|
$CFLAGS << " -Wno-dangling-else"
|
data/ext/polyphony/libev.h
CHANGED
data/ext/polyphony/polyphony.c
CHANGED
|
@@ -66,6 +66,10 @@ VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, V
|
|
|
66
66
|
return Backend_recv(BACKEND(), io, buffer, length, pos);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
VALUE Polyphony_backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
|
|
70
|
+
return Backend_recvmsg(BACKEND(), io, buffer, maxlen, pos, flags, maxcontrollen, opts);
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
70
74
|
return Backend_recv_loop(BACKEND(), io, maxlen);
|
|
71
75
|
}
|
|
@@ -78,6 +82,10 @@ VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
|
|
|
78
82
|
return Backend_send(BACKEND(), io, msg, flags);
|
|
79
83
|
}
|
|
80
84
|
|
|
85
|
+
VALUE Polyphony_backend_sendmsg(VALUE self, VALUE io, VALUE msg, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
|
|
86
|
+
return Backend_sendmsg(BACKEND(), io, msg, flags, dest_sockaddr, controls);
|
|
87
|
+
}
|
|
88
|
+
|
|
81
89
|
VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
|
|
82
90
|
return Backend_sendv(BACKEND(), io, ary, flags);
|
|
83
91
|
}
|
|
@@ -181,9 +189,11 @@ void Init_Polyphony(void) {
|
|
|
181
189
|
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
|
|
182
190
|
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
|
|
183
191
|
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
|
|
192
|
+
rb_define_singleton_method(mPolyphony, "backend_recvmsg", Polyphony_backend_recvmsg, 7);
|
|
184
193
|
rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 2);
|
|
185
194
|
rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
|
|
186
195
|
rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
|
|
196
|
+
rb_define_singleton_method(mPolyphony, "backend_sendmsg", Polyphony_backend_sendmsg, 5);
|
|
187
197
|
rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
|
|
188
198
|
rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
|
|
189
199
|
rb_define_singleton_method(mPolyphony, "backend_splice", Polyphony_backend_splice, 3);
|
data/ext/polyphony/polyphony.h
CHANGED
|
@@ -100,9 +100,11 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
|
|
100
100
|
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos);
|
|
101
101
|
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen);
|
|
102
102
|
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos);
|
|
103
|
+
VALUE Backend_recvmsg(VALUE self, VALUE io, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts);
|
|
103
104
|
VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen);
|
|
104
105
|
VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
|
105
106
|
VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
|
|
107
|
+
VALUE Backend_sendmsg(VALUE self, VALUE io, VALUE msg, VALUE flags, VALUE dest_sockaddr, VALUE controls);
|
|
106
108
|
VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
|
|
107
109
|
VALUE Backend_sleep(VALUE self, VALUE duration);
|
|
108
110
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
data/lib/polyphony/core/sync.rb
CHANGED
|
@@ -58,6 +58,58 @@ module Polyphony
|
|
|
58
58
|
@holding_fiber
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
# Obtains a lock. Raises `ThreadError` if mutex is locked by the current
|
|
62
|
+
# thread.
|
|
63
|
+
#
|
|
64
|
+
# @return [Mutex] self
|
|
65
|
+
def lock
|
|
66
|
+
raise ThreadError if owned?
|
|
67
|
+
|
|
68
|
+
@token = @store.shift
|
|
69
|
+
@holding_fiber = Fiber.current
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Releases the lock. Raises `ThreadError` if mutex is not locked by the
|
|
74
|
+
# current thread.
|
|
75
|
+
#
|
|
76
|
+
# @return [Mutex] self
|
|
77
|
+
def unlock
|
|
78
|
+
raise ThreadError if !owned?
|
|
79
|
+
|
|
80
|
+
@holding_fiber = nil
|
|
81
|
+
@store << @token if @token
|
|
82
|
+
@token = nil
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Attempts to obtain the lock and returns immediately. Returns `true` if the
|
|
86
|
+
# lock was granted.
|
|
87
|
+
#
|
|
88
|
+
# @return [true, false]
|
|
89
|
+
def try_lock
|
|
90
|
+
return false if @holding_fiber
|
|
91
|
+
|
|
92
|
+
@token = @store.shift
|
|
93
|
+
@holding_fiber = Fiber.current
|
|
94
|
+
true
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Releases the lock and sleeps timeout seconds if it is given and non-nil or
|
|
98
|
+
# forever. Raises `ThreadError` if mutex wasn’t locked by the current
|
|
99
|
+
# thread.
|
|
100
|
+
#
|
|
101
|
+
# @param timeout [nil, Number] sleep timeout
|
|
102
|
+
# @return [Number] slept time in seconds
|
|
103
|
+
def sleep(timeout = nil)
|
|
104
|
+
unlock
|
|
105
|
+
t0 = Time.now
|
|
106
|
+
Kernel.sleep(timeout)
|
|
107
|
+
t1 = Time.now
|
|
108
|
+
lock
|
|
109
|
+
|
|
110
|
+
return t1 - t0
|
|
111
|
+
end
|
|
112
|
+
|
|
61
113
|
private
|
|
62
114
|
|
|
63
115
|
# Helper method for performing a `#synchronize` when not currently holding
|
|
@@ -72,6 +124,7 @@ module Polyphony
|
|
|
72
124
|
ensure
|
|
73
125
|
@holding_fiber = nil
|
|
74
126
|
@store << @token if @token
|
|
127
|
+
@token = nil
|
|
75
128
|
end
|
|
76
129
|
end
|
|
77
130
|
end
|
|
@@ -25,20 +25,19 @@ class ::IO
|
|
|
25
25
|
|
|
26
26
|
EMPTY_HASH = {}.freeze
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# end
|
|
28
|
+
alias_method :orig_foreach, :foreach
|
|
29
|
+
def foreach(name, sep = $/, limit = nil, getline_args = EMPTY_HASH, &block)
|
|
30
|
+
# IO.orig_read(name).each_line(&block)
|
|
31
|
+
# raise NotImplementedError
|
|
32
|
+
|
|
33
|
+
if sep.is_a?(Integer)
|
|
34
|
+
sep = $/
|
|
35
|
+
limit = sep
|
|
36
|
+
end
|
|
37
|
+
File.open(name, 'r') do |f|
|
|
38
|
+
f.each_line(sep, limit, chomp: getline_args[:chomp], &block)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
42
41
|
|
|
43
42
|
alias_method :orig_read, :read
|
|
44
43
|
def read(name, length = nil, offset = nil, opt = EMPTY_HASH)
|
|
@@ -143,6 +142,8 @@ class ::IO
|
|
|
143
142
|
|
|
144
143
|
alias_method :orig_read, :read
|
|
145
144
|
def read(len = nil, buf = nil, buf_pos = 0)
|
|
145
|
+
return '' if len == 0
|
|
146
|
+
|
|
146
147
|
if buf
|
|
147
148
|
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
|
148
149
|
end
|
|
@@ -196,6 +197,30 @@ class ::IO
|
|
|
196
197
|
return nil
|
|
197
198
|
end
|
|
198
199
|
|
|
200
|
+
def each_line(sep = $/, limit = nil, chomp: false)
|
|
201
|
+
if sep.is_a?(Integer)
|
|
202
|
+
limit = sep
|
|
203
|
+
sep = $/
|
|
204
|
+
end
|
|
205
|
+
sep_size = sep.bytesize
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@read_buffer ||= +''
|
|
209
|
+
|
|
210
|
+
while true
|
|
211
|
+
while (idx = @read_buffer.index(sep))
|
|
212
|
+
line = @read_buffer.slice!(0, idx + sep_size)
|
|
213
|
+
line = line.chomp if chomp
|
|
214
|
+
yield line
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
result = readpartial(8192, @read_buffer, -1)
|
|
218
|
+
return self if !result
|
|
219
|
+
end
|
|
220
|
+
rescue EOFError
|
|
221
|
+
return self
|
|
222
|
+
end
|
|
223
|
+
|
|
199
224
|
# def print(*args)
|
|
200
225
|
# end
|
|
201
226
|
|
|
@@ -200,7 +200,7 @@ class ::OpenSSL::SSL::SSLServer
|
|
|
200
200
|
def accept_loop(ignore_errors = true)
|
|
201
201
|
loop do
|
|
202
202
|
yield accept
|
|
203
|
-
rescue
|
|
203
|
+
rescue OpenSSL::SSL::SSLError, SystemCallError => e
|
|
204
204
|
raise e unless ignore_errors
|
|
205
205
|
end
|
|
206
206
|
end
|