polyphony 0.97 → 0.99

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/examples/io/https_server_sni_2.rb +14 -8
  4. data/examples/io/irb.rb +1 -1
  5. data/ext/polyphony/backend_common.c +30 -0
  6. data/ext/polyphony/backend_common.h +1 -0
  7. data/ext/polyphony/backend_io_uring.c +125 -0
  8. data/ext/polyphony/backend_libev.c +135 -0
  9. data/ext/polyphony/extconf.rb +6 -5
  10. data/ext/polyphony/io_extensions.c +2 -0
  11. data/ext/polyphony/libev.h +0 -2
  12. data/ext/polyphony/polyphony.c +10 -0
  13. data/ext/polyphony/polyphony.h +2 -0
  14. data/lib/polyphony/adapters/irb.rb +0 -2
  15. data/lib/polyphony/core/sync.rb +53 -0
  16. data/lib/polyphony/extensions/io.rb +39 -14
  17. data/lib/polyphony/extensions/openssl.rb +1 -1
  18. data/lib/polyphony/extensions/socket.rb +30 -1
  19. data/lib/polyphony/version.rb +1 -1
  20. data/lib/polyphony.rb +4 -0
  21. data/test/test_io.rb +14 -7
  22. data/test/test_socket.rb +131 -10
  23. data/test/test_sync.rb +42 -1
  24. data/test/test_thread.rb +2 -1
  25. data/vendor/liburing/.github/workflows/build.yml +7 -16
  26. data/vendor/liburing/.gitignore +5 -0
  27. data/vendor/liburing/CHANGELOG +23 -1
  28. data/vendor/liburing/Makefile +4 -3
  29. data/vendor/liburing/Makefile.common +1 -0
  30. data/vendor/liburing/README +48 -0
  31. data/vendor/liburing/configure +76 -6
  32. data/vendor/liburing/debian/changelog +11 -0
  33. data/vendor/liburing/debian/control +7 -16
  34. data/vendor/liburing/debian/liburing-dev.manpages +3 -6
  35. data/vendor/liburing/debian/liburing2.install +1 -0
  36. data/vendor/liburing/debian/liburing2.symbols +56 -0
  37. data/vendor/liburing/debian/rules +15 -68
  38. data/vendor/liburing/examples/Makefile +4 -0
  39. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  40. data/vendor/liburing/examples/io_uring-udp.c +1 -1
  41. data/vendor/liburing/examples/send-zerocopy.c +315 -56
  42. data/vendor/liburing/examples/ucontext-cp.c +2 -17
  43. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  44. data/vendor/liburing/liburing.pc.in +1 -1
  45. data/vendor/liburing/liburing.spec +1 -1
  46. data/vendor/liburing/make-debs.sh +3 -3
  47. data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
  48. data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
  49. data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
  50. data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
  51. data/vendor/liburing/man/io_uring_check_version.3 +72 -0
  52. data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
  53. data/vendor/liburing/man/io_uring_major_version.3 +1 -0
  54. data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
  55. data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
  56. data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
  57. data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
  58. data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
  59. data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
  60. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
  61. data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
  62. data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
  63. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
  64. data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
  65. data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
  66. data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
  67. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
  68. data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
  69. data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
  70. data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
  71. data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
  72. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
  73. data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
  74. data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
  75. data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
  76. data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
  77. data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
  78. data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
  79. data/vendor/liburing/man/io_uring_register.2 +15 -9
  80. data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
  81. data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
  82. data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
  83. data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
  84. data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
  85. data/vendor/liburing/man/io_uring_register_files.3 +60 -5
  86. data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
  87. data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
  88. data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
  89. data/vendor/liburing/man/io_uring_setup.2 +31 -2
  90. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
  91. data/vendor/liburing/src/Makefile +25 -3
  92. data/vendor/liburing/src/ffi.c +15 -0
  93. data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
  94. data/vendor/liburing/src/include/liburing.h +190 -148
  95. data/vendor/liburing/src/int_flags.h +1 -0
  96. data/vendor/liburing/src/lib.h +5 -16
  97. data/vendor/liburing/src/liburing-ffi.map +172 -0
  98. data/vendor/liburing/src/liburing.map +11 -0
  99. data/vendor/liburing/src/nolibc.c +9 -2
  100. data/vendor/liburing/src/queue.c +2 -2
  101. data/vendor/liburing/src/register.c +66 -96
  102. data/vendor/liburing/src/setup.c +5 -4
  103. data/vendor/liburing/src/version.c +21 -0
  104. data/vendor/liburing/test/232c93d07b74.c +3 -3
  105. data/vendor/liburing/test/35fa71a030ca.c +3 -3
  106. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  107. data/vendor/liburing/test/917257daa0fe.c +1 -1
  108. data/vendor/liburing/test/Makefile +27 -7
  109. data/vendor/liburing/test/a0908ae19763.c +2 -2
  110. data/vendor/liburing/test/a4c0b3decb33.c +2 -2
  111. data/vendor/liburing/test/accept-link.c +4 -4
  112. data/vendor/liburing/test/accept-reuse.c +5 -7
  113. data/vendor/liburing/test/accept.c +34 -31
  114. data/vendor/liburing/test/b19062a56726.c +1 -1
  115. data/vendor/liburing/test/buf-ring.c +58 -4
  116. data/vendor/liburing/test/ce593a6c480a.c +2 -2
  117. data/vendor/liburing/test/close-opath.c +2 -1
  118. data/vendor/liburing/test/connect.c +8 -0
  119. data/vendor/liburing/test/cq-overflow.c +14 -8
  120. data/vendor/liburing/test/d4ae271dfaae.c +1 -1
  121. data/vendor/liburing/test/defer-taskrun.c +64 -9
  122. data/vendor/liburing/test/defer.c +1 -1
  123. data/vendor/liburing/test/double-poll-crash.c +3 -3
  124. data/vendor/liburing/test/eeed8b54e0df.c +8 -3
  125. data/vendor/liburing/test/eploop.c +74 -0
  126. data/vendor/liburing/test/eventfd-ring.c +1 -1
  127. data/vendor/liburing/test/eventfd.c +1 -1
  128. data/vendor/liburing/test/evloop.c +73 -0
  129. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  130. data/vendor/liburing/test/fadvise.c +1 -1
  131. data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
  132. data/vendor/liburing/test/fd-pass.c +35 -16
  133. data/vendor/liburing/test/file-register.c +61 -0
  134. data/vendor/liburing/test/file-verify.c +2 -2
  135. data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
  136. data/vendor/liburing/test/fixed-link.c +1 -1
  137. data/vendor/liburing/test/fsnotify.c +118 -0
  138. data/vendor/liburing/test/hardlink.c +1 -1
  139. data/vendor/liburing/test/helpers.c +54 -2
  140. data/vendor/liburing/test/helpers.h +4 -0
  141. data/vendor/liburing/test/io-cancel.c +3 -1
  142. data/vendor/liburing/test/io_uring_passthrough.c +39 -8
  143. data/vendor/liburing/test/io_uring_setup.c +3 -80
  144. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  145. data/vendor/liburing/test/iopoll.c +90 -4
  146. data/vendor/liburing/test/lfs-openat-write.c +7 -9
  147. data/vendor/liburing/test/lfs-openat.c +6 -8
  148. data/vendor/liburing/test/link_drain.c +31 -5
  149. data/vendor/liburing/test/madvise.c +1 -1
  150. data/vendor/liburing/test/msg-ring-flags.c +192 -0
  151. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  152. data/vendor/liburing/test/msg-ring.c +173 -13
  153. data/vendor/liburing/test/multicqes_drain.c +22 -19
  154. data/vendor/liburing/test/nvme.h +4 -3
  155. data/vendor/liburing/test/pipe-bug.c +95 -0
  156. data/vendor/liburing/test/poll-link.c +3 -3
  157. data/vendor/liburing/test/poll-many.c +41 -19
  158. data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
  159. data/vendor/liburing/test/poll-race-mshot.c +292 -0
  160. data/vendor/liburing/test/poll-race.c +105 -0
  161. data/vendor/liburing/test/poll.c +244 -26
  162. data/vendor/liburing/test/pollfree.c +5 -5
  163. data/vendor/liburing/test/read-before-exit.c +20 -3
  164. data/vendor/liburing/test/read-write.c +2 -0
  165. data/vendor/liburing/test/recv-multishot.c +96 -3
  166. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  167. data/vendor/liburing/test/rename.c +1 -1
  168. data/vendor/liburing/test/ring-leak.c +0 -1
  169. data/vendor/liburing/test/ring-leak2.c +1 -1
  170. data/vendor/liburing/test/ringbuf-read.c +10 -6
  171. data/vendor/liburing/test/send-zerocopy.c +273 -103
  172. data/vendor/liburing/test/send_recv.c +7 -4
  173. data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
  174. data/vendor/liburing/test/single-issuer.c +7 -9
  175. data/vendor/liburing/test/skip-cqe.c +3 -4
  176. data/vendor/liburing/test/socket.c +0 -1
  177. data/vendor/liburing/test/sq-poll-dup.c +10 -3
  178. data/vendor/liburing/test/sq-poll-kthread.c +1 -1
  179. data/vendor/liburing/test/sq-poll-share.c +3 -2
  180. data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
  181. data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
  182. data/vendor/liburing/test/symlink.c +2 -1
  183. data/vendor/liburing/test/test.h +2 -1
  184. data/vendor/liburing/test/timeout-new.c +11 -7
  185. data/vendor/liburing/test/timeout.c +1 -2
  186. data/vendor/liburing/test/unlink.c +1 -1
  187. data/vendor/liburing/test/version.c +25 -0
  188. data/vendor/liburing/test/wakeup-hang.c +1 -1
  189. data/vendor/liburing/test/xattr.c +8 -4
  190. metadata +42 -6
  191. data/vendor/liburing/debian/compat +0 -1
  192. data/vendor/liburing/debian/liburing1-udeb.install +0 -1
  193. data/vendor/liburing/debian/liburing1.install +0 -1
  194. data/vendor/liburing/debian/liburing1.symbols +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a8218fc4160e0772ee3aada1f72ea9d063724ccf9b0aee7dfa6e9e4d69ebfe4
4
- data.tar.gz: 74aae84e991cd4330ad282553061b29e71a6434ce2dafc9985c62feb3a966a68
3
+ metadata.gz: 4696bb7b13f68b379c29d5c38257e57c13aefd299f88727107e2f0f0a3c7d360
4
+ data.tar.gz: 94a3eeb8575d0d5fe6f143ab41351024b50c4c4cf919edec6c8155d9ead2831e
5
5
  SHA512:
6
- metadata.gz: 772d0be4ef2f723fa27cc5ecb8ef9e9b5d012c501a364ab23dce7d145fc6d156d5e219e52e871a2aadb41a397c5fb044c8aaee9b42906f4894ff3447af0e93ba
7
- data.tar.gz: b74d6958ea8a77ffee45aed8184091b5ef54cb4fcaca9798351533b13d2f2202f28ab95f56a26e09692bf40f00e723d2df9c99007dbe10631d1c69c523fb3a58
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
- # server.accept_loop do |socket|
31
- server.accept_loop do |socket|
32
- # while (socket = (server.accept)
33
- spin do
34
- while (data = socket.gets("\n", 8192))
35
- if data.chomp.empty?
36
- socket << "HTTP/1.1 200 OK\nConnection: close\nContent-Length: 4\n\nfoo\n"
37
- break
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'irb'
5
- require 'polyphony/adapters/irb'
5
+ require 'polyphony'
6
6
 
7
7
  $counter = 0
8
8
  timer = spin do
@@ -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
 
@@ -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
- $defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
59
- $defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
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"
@@ -21,7 +21,9 @@ ID ID_write;
21
21
 
22
22
  VALUE SYM_backend_read;
23
23
  VALUE SYM_backend_recv;
24
+ VALUE SYM_backend_recvmsg;
24
25
  VALUE SYM_backend_send;
26
+ VALUE SYM_backend_sendmsg;
25
27
  VALUE SYM_backend_write;
26
28
  VALUE SYM_call;
27
29
  VALUE SYM_comment;
@@ -1,5 +1,3 @@
1
- #define EV_STANDALONE
2
-
3
1
  #ifdef POLYPHONY_BACKEND_LIBEV
4
2
 
5
3
  /* keeps ev from requiring config.h */
@@ -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);
@@ -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);
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'polyphony'
4
-
5
3
  module Kernel
6
4
  alias_method :gets, :orig_gets
7
5
  end
@@ -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
- # alias_method :orig_foreach, :foreach
29
- # def foreach(_name, _sep = $/, _limit = nil, _getline_args = EMPTY_HASH,
30
- # &_block)
31
- # # IO.orig_read(name).each_line(&block)
32
- # raise NotImplementedError
33
-
34
- # # if sep.is_a?(Integer)
35
- # # sep = $/
36
- # # limit = sep
37
- # # end
38
- # # File.open(name, 'r') do |f|
39
- # # f.each_line(sep, limit, getline_args, &block)
40
- # # end
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 SystemCallError, StandardError => e
203
+ rescue OpenSSL::SSL::SSLError, SystemCallError => e
204
204
  raise e unless ignore_errors
205
205
  end
206
206
  end