polyphony 0.97 → 0.99
Sign up to get free protection for your applications and to get access to all the features.
- 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
|