polyphony 0.94 → 0.96

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.
Files changed (318) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +3 -3
  3. data/.github/workflows/test_io_uring.yml +4 -4
  4. data/.gitignore +3 -3
  5. data/CHANGELOG.md +19 -0
  6. data/docs/api-reference/fiber.md +2 -2
  7. data/docs/api-reference/object.md +3 -3
  8. data/docs/main-concepts/exception-handling.md +2 -2
  9. data/examples/adapters/redis_blpop.rb +4 -3
  10. data/examples/adapters/redis_channels.rb +16 -7
  11. data/examples/core/await.rb +1 -1
  12. data/examples/io/readline.rb +19 -0
  13. data/ext/polyphony/backend_common.c +25 -3
  14. data/ext/polyphony/backend_io_uring.c +18 -16
  15. data/ext/polyphony/backend_libev.c +2 -2
  16. data/ext/polyphony/event.c +1 -1
  17. data/ext/polyphony/extconf.rb +5 -3
  18. data/ext/polyphony/fiber.c +5 -13
  19. data/ext/polyphony/io_extensions.c +1 -1
  20. data/ext/polyphony/pipe.c +1 -1
  21. data/ext/polyphony/polyphony.c +1 -1
  22. data/ext/polyphony/polyphony_ext.c +1 -1
  23. data/ext/polyphony/queue.c +1 -1
  24. data/ext/polyphony/ring_buffer.c +1 -0
  25. data/ext/polyphony/socket_extensions.c +1 -1
  26. data/ext/polyphony/thread.c +1 -1
  27. data/lib/polyphony/adapters/readline.rb +6 -4
  28. data/lib/polyphony/adapters/redis.rb +28 -87
  29. data/lib/polyphony/core/channel.rb +15 -0
  30. data/lib/polyphony/core/sync.rb +4 -0
  31. data/lib/polyphony/debugger.rb +2 -2
  32. data/lib/polyphony/extensions/socket.rb +2 -0
  33. data/lib/polyphony/version.rb +1 -1
  34. data/lib/polyphony.rb +4 -0
  35. data/polyphony.gemspec +10 -10
  36. data/test/helper.rb +0 -5
  37. data/test/test_backend.rb +5 -1
  38. data/test/test_enumerator.rb +46 -0
  39. data/test/test_ext.rb +63 -0
  40. data/test/test_io.rb +241 -216
  41. data/test/test_socket.rb +1 -1
  42. data/test/test_thread_pool.rb +5 -5
  43. data/vendor/liburing/.github/workflows/build.yml +51 -5
  44. data/vendor/liburing/.github/workflows/shellcheck.yml +1 -1
  45. data/vendor/liburing/.gitignore +6 -123
  46. data/vendor/liburing/CHANGELOG +35 -0
  47. data/vendor/liburing/CITATION.cff +11 -0
  48. data/vendor/liburing/LICENSE +16 -3
  49. data/vendor/liburing/Makefile +3 -1
  50. data/vendor/liburing/Makefile.common +1 -0
  51. data/vendor/liburing/README +14 -2
  52. data/vendor/liburing/SECURITY.md +6 -0
  53. data/vendor/liburing/configure +16 -15
  54. data/vendor/liburing/examples/Makefile +4 -1
  55. data/vendor/liburing/examples/io_uring-udp.c +395 -0
  56. data/vendor/liburing/examples/poll-bench.c +101 -0
  57. data/vendor/liburing/examples/send-zerocopy.c +339 -0
  58. data/vendor/liburing/liburing.spec +1 -1
  59. data/vendor/liburing/man/io_uring.7 +38 -11
  60. data/vendor/liburing/man/io_uring_buf_ring_add.3 +53 -0
  61. data/vendor/liburing/man/io_uring_buf_ring_advance.3 +31 -0
  62. data/vendor/liburing/man/io_uring_buf_ring_cq_advance.3 +41 -0
  63. data/vendor/liburing/man/io_uring_buf_ring_init.3 +30 -0
  64. data/vendor/liburing/man/io_uring_buf_ring_mask.3 +27 -0
  65. data/vendor/liburing/man/io_uring_cq_advance.3 +29 -15
  66. data/vendor/liburing/man/io_uring_cq_has_overflow.3 +25 -0
  67. data/vendor/liburing/man/io_uring_cq_ready.3 +9 -8
  68. data/vendor/liburing/man/io_uring_cqe_get_data.3 +32 -13
  69. data/vendor/liburing/man/io_uring_cqe_get_data64.3 +1 -0
  70. data/vendor/liburing/man/io_uring_cqe_seen.3 +22 -12
  71. data/vendor/liburing/man/io_uring_enter.2 +249 -32
  72. data/vendor/liburing/man/io_uring_enter2.2 +1 -0
  73. data/vendor/liburing/man/io_uring_free_probe.3 +11 -8
  74. data/vendor/liburing/man/io_uring_get_events.3 +33 -0
  75. data/vendor/liburing/man/io_uring_get_probe.3 +9 -8
  76. data/vendor/liburing/man/io_uring_get_sqe.3 +29 -10
  77. data/vendor/liburing/man/io_uring_opcode_supported.3 +11 -10
  78. data/vendor/liburing/man/io_uring_peek_cqe.3 +38 -0
  79. data/vendor/liburing/man/io_uring_prep_accept.3 +197 -0
  80. data/vendor/liburing/man/io_uring_prep_accept_direct.3 +1 -0
  81. data/vendor/liburing/man/io_uring_prep_cancel.3 +118 -0
  82. data/vendor/liburing/man/io_uring_prep_cancel64.3 +1 -0
  83. data/vendor/liburing/man/io_uring_prep_close.3 +59 -0
  84. data/vendor/liburing/man/io_uring_prep_close_direct.3 +1 -0
  85. data/vendor/liburing/man/io_uring_prep_connect.3 +66 -0
  86. data/vendor/liburing/man/io_uring_prep_fadvise.3 +59 -0
  87. data/vendor/liburing/man/io_uring_prep_fallocate.3 +59 -0
  88. data/vendor/liburing/man/io_uring_prep_files_update.3 +92 -0
  89. data/vendor/liburing/man/io_uring_prep_fsync.3 +70 -0
  90. data/vendor/liburing/man/io_uring_prep_link.3 +1 -0
  91. data/vendor/liburing/man/io_uring_prep_linkat.3 +91 -0
  92. data/vendor/liburing/man/io_uring_prep_madvise.3 +56 -0
  93. data/vendor/liburing/man/io_uring_prep_mkdir.3 +1 -0
  94. data/vendor/liburing/man/io_uring_prep_mkdirat.3 +83 -0
  95. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +39 -25
  96. data/vendor/liburing/man/io_uring_prep_multishot_accept.3 +1 -0
  97. data/vendor/liburing/man/io_uring_prep_multishot_accept_direct.3 +1 -0
  98. data/vendor/liburing/man/io_uring_prep_nop.3 +28 -0
  99. data/vendor/liburing/man/io_uring_prep_openat.3 +117 -0
  100. data/vendor/liburing/man/io_uring_prep_openat2.3 +117 -0
  101. data/vendor/liburing/man/io_uring_prep_openat2_direct.3 +1 -0
  102. data/vendor/liburing/man/io_uring_prep_openat_direct.3 +1 -0
  103. data/vendor/liburing/man/io_uring_prep_poll_add.3 +72 -0
  104. data/vendor/liburing/man/io_uring_prep_poll_multishot.3 +1 -0
  105. data/vendor/liburing/man/io_uring_prep_poll_remove.3 +55 -0
  106. data/vendor/liburing/man/io_uring_prep_poll_update.3 +89 -0
  107. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +131 -0
  108. data/vendor/liburing/man/io_uring_prep_read.3 +33 -14
  109. data/vendor/liburing/man/io_uring_prep_read_fixed.3 +39 -21
  110. data/vendor/liburing/man/io_uring_prep_readv.3 +49 -15
  111. data/vendor/liburing/man/io_uring_prep_readv2.3 +49 -17
  112. data/vendor/liburing/man/io_uring_prep_recv.3 +105 -0
  113. data/vendor/liburing/man/io_uring_prep_recv_multishot.3 +1 -0
  114. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +124 -0
  115. data/vendor/liburing/man/io_uring_prep_recvmsg_multishot.3 +1 -0
  116. data/vendor/liburing/man/io_uring_prep_remove_buffers.3 +52 -0
  117. data/vendor/liburing/man/io_uring_prep_rename.3 +1 -0
  118. data/vendor/liburing/man/io_uring_prep_renameat.3 +96 -0
  119. data/vendor/liburing/man/io_uring_prep_send.3 +57 -0
  120. data/vendor/liburing/man/io_uring_prep_send_zc.3 +64 -0
  121. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +69 -0
  122. data/vendor/liburing/man/io_uring_prep_shutdown.3 +53 -0
  123. data/vendor/liburing/man/io_uring_prep_socket.3 +118 -0
  124. data/vendor/liburing/man/io_uring_prep_socket_direct.3 +1 -0
  125. data/vendor/liburing/man/io_uring_prep_socket_direct_alloc.3 +1 -0
  126. data/vendor/liburing/man/io_uring_prep_splice.3 +80 -0
  127. data/vendor/liburing/man/io_uring_prep_statx.3 +74 -0
  128. data/vendor/liburing/man/io_uring_prep_symlink.3 +1 -0
  129. data/vendor/liburing/man/io_uring_prep_symlinkat.3 +85 -0
  130. data/vendor/liburing/man/io_uring_prep_sync_file_range.3 +59 -0
  131. data/vendor/liburing/man/io_uring_prep_tee.3 +74 -0
  132. data/vendor/liburing/man/io_uring_prep_timeout.3 +95 -0
  133. data/vendor/liburing/man/io_uring_prep_timeout_remove.3 +1 -0
  134. data/vendor/liburing/man/io_uring_prep_timeout_update.3 +98 -0
  135. data/vendor/liburing/man/io_uring_prep_unlink.3 +1 -0
  136. data/vendor/liburing/man/io_uring_prep_unlinkat.3 +82 -0
  137. data/vendor/liburing/man/io_uring_prep_write.3 +32 -15
  138. data/vendor/liburing/man/io_uring_prep_write_fixed.3 +39 -21
  139. data/vendor/liburing/man/io_uring_prep_writev.3 +50 -16
  140. data/vendor/liburing/man/io_uring_prep_writev2.3 +50 -17
  141. data/vendor/liburing/man/io_uring_queue_exit.3 +3 -4
  142. data/vendor/liburing/man/io_uring_queue_init.3 +58 -13
  143. data/vendor/liburing/man/io_uring_queue_init_params.3 +1 -0
  144. data/vendor/liburing/man/io_uring_recvmsg_cmsg_firsthdr.3 +1 -0
  145. data/vendor/liburing/man/io_uring_recvmsg_cmsg_nexthdr.3 +1 -0
  146. data/vendor/liburing/man/io_uring_recvmsg_name.3 +1 -0
  147. data/vendor/liburing/man/io_uring_recvmsg_out.3 +78 -0
  148. data/vendor/liburing/man/io_uring_recvmsg_payload.3 +1 -0
  149. data/vendor/liburing/man/io_uring_recvmsg_payload_length.3 +1 -0
  150. data/vendor/liburing/man/io_uring_recvmsg_validate.3 +1 -0
  151. data/vendor/liburing/man/io_uring_register.2 +153 -13
  152. data/vendor/liburing/man/io_uring_register_buf_ring.3 +140 -0
  153. data/vendor/liburing/man/io_uring_register_buffers.3 +32 -12
  154. data/vendor/liburing/man/io_uring_register_eventfd.3 +51 -0
  155. data/vendor/liburing/man/io_uring_register_eventfd_async.3 +1 -0
  156. data/vendor/liburing/man/io_uring_register_file_alloc_range.3 +52 -0
  157. data/vendor/liburing/man/io_uring_register_files.3 +33 -11
  158. data/vendor/liburing/man/io_uring_register_files_sparse.3 +1 -0
  159. data/vendor/liburing/man/io_uring_register_iowq_aff.3 +61 -0
  160. data/vendor/liburing/man/io_uring_register_iowq_max_workers.3 +71 -0
  161. data/vendor/liburing/man/io_uring_register_ring_fd.3 +49 -0
  162. data/vendor/liburing/man/io_uring_register_sync_cancel.3 +71 -0
  163. data/vendor/liburing/man/io_uring_setup.2 +119 -13
  164. data/vendor/liburing/man/io_uring_sq_ready.3 +14 -8
  165. data/vendor/liburing/man/io_uring_sq_space_left.3 +9 -9
  166. data/vendor/liburing/man/io_uring_sqe_set_data.3 +29 -11
  167. data/vendor/liburing/man/io_uring_sqe_set_data64.3 +1 -0
  168. data/vendor/liburing/man/io_uring_sqe_set_flags.3 +38 -11
  169. data/vendor/liburing/man/io_uring_sqring_wait.3 +13 -9
  170. data/vendor/liburing/man/io_uring_submit.3 +29 -12
  171. data/vendor/liburing/man/io_uring_submit_and_get_events.3 +31 -0
  172. data/vendor/liburing/man/io_uring_submit_and_wait.3 +16 -12
  173. data/vendor/liburing/man/io_uring_submit_and_wait_timeout.3 +30 -23
  174. data/vendor/liburing/man/io_uring_unregister_buf_ring.3 +30 -0
  175. data/vendor/liburing/man/io_uring_unregister_buffers.3 +11 -10
  176. data/vendor/liburing/man/io_uring_unregister_eventfd.3 +1 -0
  177. data/vendor/liburing/man/io_uring_unregister_files.3 +11 -10
  178. data/vendor/liburing/man/io_uring_unregister_iowq_aff.3 +1 -0
  179. data/vendor/liburing/man/io_uring_unregister_ring_fd.3 +32 -0
  180. data/vendor/liburing/man/io_uring_wait_cqe.3 +19 -12
  181. data/vendor/liburing/man/io_uring_wait_cqe_nr.3 +21 -14
  182. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +27 -13
  183. data/vendor/liburing/man/io_uring_wait_cqes.3 +24 -14
  184. data/vendor/liburing/src/Makefile +8 -7
  185. data/vendor/liburing/src/arch/aarch64/lib.h +48 -0
  186. data/vendor/liburing/src/arch/aarch64/syscall.h +0 -4
  187. data/vendor/liburing/src/arch/generic/lib.h +0 -4
  188. data/vendor/liburing/src/arch/generic/syscall.h +29 -16
  189. data/vendor/liburing/src/arch/syscall-defs.h +41 -14
  190. data/vendor/liburing/src/arch/x86/lib.h +0 -21
  191. data/vendor/liburing/src/arch/x86/syscall.h +146 -10
  192. data/vendor/liburing/src/include/liburing/io_uring.h +245 -5
  193. data/vendor/liburing/src/include/liburing.h +468 -35
  194. data/vendor/liburing/src/int_flags.h +1 -0
  195. data/vendor/liburing/src/lib.h +20 -16
  196. data/vendor/liburing/src/liburing.map +16 -0
  197. data/vendor/liburing/src/nolibc.c +1 -1
  198. data/vendor/liburing/src/queue.c +87 -55
  199. data/vendor/liburing/src/register.c +129 -53
  200. data/vendor/liburing/src/setup.c +65 -28
  201. data/vendor/liburing/src/syscall.c +14 -32
  202. data/vendor/liburing/src/syscall.h +12 -64
  203. data/vendor/liburing/test/{232c93d07b74-test.c → 232c93d07b74.c} +8 -9
  204. data/vendor/liburing/test/{35fa71a030ca-test.c → 35fa71a030ca.c} +4 -4
  205. data/vendor/liburing/test/{500f9fbadef8-test.c → 500f9fbadef8.c} +7 -7
  206. data/vendor/liburing/test/{7ad0e4b2f83c-test.c → 7ad0e4b2f83c.c} +8 -7
  207. data/vendor/liburing/test/{8a9973408177-test.c → 8a9973408177.c} +4 -3
  208. data/vendor/liburing/test/{917257daa0fe-test.c → 917257daa0fe.c} +3 -2
  209. data/vendor/liburing/test/Makefile +60 -62
  210. data/vendor/liburing/test/{a0908ae19763-test.c → a0908ae19763.c} +3 -2
  211. data/vendor/liburing/test/{a4c0b3decb33-test.c → a4c0b3decb33.c} +3 -2
  212. data/vendor/liburing/test/accept-link.c +5 -4
  213. data/vendor/liburing/test/accept-reuse.c +17 -16
  214. data/vendor/liburing/test/accept-test.c +14 -10
  215. data/vendor/liburing/test/accept.c +529 -107
  216. data/vendor/liburing/test/across-fork.c +7 -6
  217. data/vendor/liburing/test/{b19062a56726-test.c → b19062a56726.c} +3 -2
  218. data/vendor/liburing/test/{b5837bd5311d-test.c → b5837bd5311d.c} +10 -9
  219. data/vendor/liburing/test/buf-ring.c +420 -0
  220. data/vendor/liburing/test/{ce593a6c480a-test.c → ce593a6c480a.c} +15 -12
  221. data/vendor/liburing/test/connect.c +8 -7
  222. data/vendor/liburing/test/cq-full.c +5 -4
  223. data/vendor/liburing/test/cq-overflow.c +242 -12
  224. data/vendor/liburing/test/cq-peek-batch.c +5 -4
  225. data/vendor/liburing/test/cq-ready.c +5 -4
  226. data/vendor/liburing/test/cq-size.c +5 -4
  227. data/vendor/liburing/test/{d4ae271dfaae-test.c → d4ae271dfaae.c} +2 -2
  228. data/vendor/liburing/test/{d77a67ed5f27-test.c → d77a67ed5f27.c} +6 -6
  229. data/vendor/liburing/test/defer-taskrun.c +336 -0
  230. data/vendor/liburing/test/defer.c +26 -14
  231. data/vendor/liburing/test/double-poll-crash.c +15 -5
  232. data/vendor/liburing/test/drop-submit.c +5 -3
  233. data/vendor/liburing/test/{eeed8b54e0df-test.c → eeed8b54e0df.c} +7 -6
  234. data/vendor/liburing/test/empty-eownerdead.c +4 -4
  235. data/vendor/liburing/test/eventfd-disable.c +48 -20
  236. data/vendor/liburing/test/eventfd-reg.c +10 -9
  237. data/vendor/liburing/test/eventfd-ring.c +13 -12
  238. data/vendor/liburing/test/eventfd.c +13 -12
  239. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  240. data/vendor/liburing/test/fadvise.c +3 -3
  241. data/vendor/liburing/test/fallocate.c +16 -9
  242. data/vendor/liburing/test/{fc2a85cb02ef-test.c → fc2a85cb02ef.c} +4 -3
  243. data/vendor/liburing/test/fd-pass.c +187 -0
  244. data/vendor/liburing/test/file-register.c +302 -36
  245. data/vendor/liburing/test/file-update.c +62 -4
  246. data/vendor/liburing/test/file-verify.c +6 -2
  247. data/vendor/liburing/test/files-exit-hang-poll.c +11 -25
  248. data/vendor/liburing/test/files-exit-hang-timeout.c +13 -10
  249. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  250. data/vendor/liburing/test/fixed-link.c +10 -10
  251. data/vendor/liburing/test/fixed-reuse.c +160 -0
  252. data/vendor/liburing/test/fpos.c +6 -3
  253. data/vendor/liburing/test/fsync.c +3 -3
  254. data/vendor/liburing/test/hardlink.c +10 -6
  255. data/vendor/liburing/test/helpers.c +137 -4
  256. data/vendor/liburing/test/helpers.h +27 -0
  257. data/vendor/liburing/test/io-cancel.c +16 -11
  258. data/vendor/liburing/test/io_uring_enter.c +46 -81
  259. data/vendor/liburing/test/io_uring_passthrough.c +451 -0
  260. data/vendor/liburing/test/io_uring_register.c +59 -229
  261. data/vendor/liburing/test/io_uring_setup.c +24 -29
  262. data/vendor/liburing/test/iopoll-leak.c +85 -0
  263. data/vendor/liburing/test/iopoll.c +16 -9
  264. data/vendor/liburing/test/lfs-openat-write.c +3 -1
  265. data/vendor/liburing/test/link-timeout.c +4 -3
  266. data/vendor/liburing/test/link.c +8 -7
  267. data/vendor/liburing/test/madvise.c +2 -2
  268. data/vendor/liburing/test/mkdir.c +9 -5
  269. data/vendor/liburing/test/msg-ring.c +46 -20
  270. data/vendor/liburing/test/multicqes_drain.c +51 -12
  271. data/vendor/liburing/test/nolibc.c +60 -0
  272. data/vendor/liburing/test/nop.c +78 -16
  273. data/vendor/liburing/test/nvme.h +168 -0
  274. data/vendor/liburing/test/open-direct-link.c +188 -0
  275. data/vendor/liburing/test/open-direct-pick.c +180 -0
  276. data/vendor/liburing/test/openat2.c +3 -3
  277. data/vendor/liburing/test/poll-cancel-all.c +472 -0
  278. data/vendor/liburing/test/poll-link.c +9 -18
  279. data/vendor/liburing/test/poll-mshot-overflow.c +162 -0
  280. data/vendor/liburing/test/poll-mshot-update.c +83 -33
  281. data/vendor/liburing/test/pollfree.c +2 -2
  282. data/vendor/liburing/test/read-before-exit.c +112 -0
  283. data/vendor/liburing/test/read-write.c +83 -1
  284. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  285. data/vendor/liburing/test/recv-msgall.c +265 -0
  286. data/vendor/liburing/test/recv-multishot.c +505 -0
  287. data/vendor/liburing/test/rename.c +2 -5
  288. data/vendor/liburing/test/ring-leak.c +97 -0
  289. data/vendor/liburing/test/ringbuf-read.c +200 -0
  290. data/vendor/liburing/test/rsrc_tags.c +25 -13
  291. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  292. data/vendor/liburing/test/runtests.sh +18 -20
  293. data/vendor/liburing/test/rw_merge_test.c +3 -2
  294. data/vendor/liburing/test/send-zerocopy.c +684 -0
  295. data/vendor/liburing/test/send_recv.c +49 -2
  296. data/vendor/liburing/test/send_recvmsg.c +165 -55
  297. data/vendor/liburing/test/shutdown.c +3 -4
  298. data/vendor/liburing/test/sigfd-deadlock.c +22 -8
  299. data/vendor/liburing/test/single-issuer.c +171 -0
  300. data/vendor/liburing/test/socket-rw-eagain.c +2 -12
  301. data/vendor/liburing/test/socket-rw-offset.c +2 -11
  302. data/vendor/liburing/test/socket-rw.c +2 -11
  303. data/vendor/liburing/test/socket.c +409 -0
  304. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  305. data/vendor/liburing/test/sq-poll-share.c +1 -1
  306. data/vendor/liburing/test/statx.c +2 -2
  307. data/vendor/liburing/test/submit-and-wait.c +108 -0
  308. data/vendor/liburing/test/submit-link-fail.c +5 -3
  309. data/vendor/liburing/test/submit-reuse.c +0 -2
  310. data/vendor/liburing/test/sync-cancel.c +235 -0
  311. data/vendor/liburing/test/test.h +35 -0
  312. data/vendor/liburing/test/timeout-overflow.c +11 -11
  313. data/vendor/liburing/test/timeout.c +7 -7
  314. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  315. data/vendor/liburing/test/unlink.c +1 -1
  316. data/vendor/liburing/test/xattr.c +425 -0
  317. metadata +160 -52
  318. data/Gemfile.lock +0 -78
@@ -0,0 +1,505 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ #include <errno.h>
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <unistd.h>
8
+ #include <arpa/inet.h>
9
+ #include <sys/types.h>
10
+ #include <sys/socket.h>
11
+ #include <pthread.h>
12
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+
16
+ #define ENORECVMULTISHOT 9999
17
+
18
+ enum early_error_t {
19
+ ERROR_NONE = 0,
20
+ ERROR_NOT_ENOUGH_BUFFERS,
21
+ ERROR_EARLY_CLOSE_SENDER,
22
+ ERROR_EARLY_CLOSE_RECEIVER,
23
+ ERROR_EARLY_OVERFLOW,
24
+ ERROR_EARLY_LAST
25
+ };
26
+
27
+ struct args {
28
+ bool stream;
29
+ bool wait_each;
30
+ bool recvmsg;
31
+ enum early_error_t early_error;
32
+ bool defer;
33
+ };
34
+
35
+ static int check_sockaddr(struct sockaddr_in *in)
36
+ {
37
+ struct in_addr expected;
38
+
39
+ inet_pton(AF_INET, "127.0.0.1", &expected);
40
+ if (in->sin_family != AF_INET) {
41
+ fprintf(stderr, "bad family %d\n", (int)htons(in->sin_family));
42
+ return -1;
43
+ }
44
+ if (memcmp(&expected, &in->sin_addr, sizeof(in->sin_addr))) {
45
+ char buff[256];
46
+ const char *addr = inet_ntop(AF_INET, &in->sin_addr, buff, sizeof(buff));
47
+
48
+ fprintf(stderr, "unexpected address %s\n", addr ? addr : "INVALID");
49
+ return -1;
50
+ }
51
+ return 0;
52
+ }
53
+
54
+ static int test(struct args *args)
55
+ {
56
+ int const N = 8;
57
+ int const N_BUFFS = N * 64;
58
+ int const N_CQE_OVERFLOW = 4;
59
+ int const min_cqes = 2;
60
+ int const NAME_LEN = sizeof(struct sockaddr_storage);
61
+ int const CONTROL_LEN = CMSG_ALIGN(sizeof(struct sockaddr_storage))
62
+ + sizeof(struct cmsghdr);
63
+ struct io_uring ring;
64
+ struct io_uring_cqe *cqe;
65
+ struct io_uring_sqe *sqe;
66
+ int fds[2], ret, i, j;
67
+ int total_sent_bytes = 0, total_recv_bytes = 0, total_dropped_bytes = 0;
68
+ int send_buff[256];
69
+ int *sent_buffs[N_BUFFS];
70
+ int *recv_buffs[N_BUFFS];
71
+ int *at;
72
+ struct io_uring_cqe recv_cqe[N_BUFFS];
73
+ int recv_cqes = 0;
74
+ bool early_error = false;
75
+ bool early_error_started = false;
76
+ struct __kernel_timespec timeout = {
77
+ .tv_sec = 1,
78
+ };
79
+ struct msghdr msg;
80
+ struct io_uring_params params = { };
81
+ int n_sqe = 32;
82
+
83
+ memset(recv_buffs, 0, sizeof(recv_buffs));
84
+
85
+ if (args->defer)
86
+ params.flags |= IORING_SETUP_SINGLE_ISSUER |
87
+ IORING_SETUP_DEFER_TASKRUN;
88
+
89
+ if (args->early_error == ERROR_EARLY_OVERFLOW) {
90
+ params.flags |= IORING_SETUP_CQSIZE;
91
+ params.cq_entries = N_CQE_OVERFLOW;
92
+ n_sqe = N_CQE_OVERFLOW;
93
+ }
94
+
95
+ ret = io_uring_queue_init_params(n_sqe, &ring, &params);
96
+ if (ret) {
97
+ fprintf(stderr, "queue init failed: %d\n", ret);
98
+ return ret;
99
+ }
100
+
101
+ ret = t_create_socket_pair(fds, args->stream);
102
+ if (ret) {
103
+ fprintf(stderr, "t_create_socket_pair failed: %d\n", ret);
104
+ return ret;
105
+ }
106
+
107
+ if (!args->stream) {
108
+ bool val = true;
109
+
110
+ /* force some cmsgs to come back to us */
111
+ ret = setsockopt(fds[0], IPPROTO_IP, IP_RECVORIGDSTADDR, &val,
112
+ sizeof(val));
113
+ if (ret) {
114
+ fprintf(stderr, "setsockopt failed %d\n", errno);
115
+ goto cleanup;
116
+ }
117
+ }
118
+
119
+ for (i = 0; i < ARRAY_SIZE(send_buff); i++)
120
+ send_buff[i] = i;
121
+
122
+ for (i = 0; i < ARRAY_SIZE(recv_buffs); i++) {
123
+ /* prepare some different sized buffers */
124
+ int buffer_size = (i % 2 == 0 && (args->stream || args->recvmsg)) ? 1 : N;
125
+
126
+ buffer_size *= sizeof(int);
127
+ if (args->recvmsg) {
128
+ buffer_size +=
129
+ sizeof(struct io_uring_recvmsg_out) +
130
+ NAME_LEN +
131
+ CONTROL_LEN;
132
+ }
133
+
134
+ recv_buffs[i] = malloc(buffer_size);
135
+
136
+ if (i > 2 && args->early_error == ERROR_NOT_ENOUGH_BUFFERS)
137
+ continue;
138
+
139
+ sqe = io_uring_get_sqe(&ring);
140
+ io_uring_prep_provide_buffers(sqe, recv_buffs[i],
141
+ buffer_size, 1, 7, i);
142
+ io_uring_sqe_set_data64(sqe, 0x999);
143
+ memset(recv_buffs[i], 0xcc, buffer_size);
144
+ if (io_uring_submit_and_wait_timeout(&ring, &cqe, 1, &timeout, NULL) < 0) {
145
+ fprintf(stderr, "provide buffers failed: %d\n", ret);
146
+ ret = -1;
147
+ goto cleanup;
148
+ }
149
+ io_uring_cqe_seen(&ring, cqe);
150
+ }
151
+
152
+ sqe = io_uring_get_sqe(&ring);
153
+ if (args->recvmsg) {
154
+ unsigned int flags = 0;
155
+
156
+ if (!args->stream)
157
+ flags |= MSG_TRUNC;
158
+
159
+ memset(&msg, 0, sizeof(msg));
160
+ msg.msg_namelen = NAME_LEN;
161
+ msg.msg_controllen = CONTROL_LEN;
162
+ io_uring_prep_recvmsg_multishot(sqe, fds[0], &msg, flags);
163
+ } else {
164
+ io_uring_prep_recv_multishot(sqe, fds[0], NULL, 0, 0);
165
+ }
166
+ sqe->flags |= IOSQE_BUFFER_SELECT;
167
+ sqe->buf_group = 7;
168
+ io_uring_sqe_set_data64(sqe, 1234);
169
+ io_uring_submit(&ring);
170
+
171
+ at = &send_buff[0];
172
+ total_sent_bytes = 0;
173
+ for (i = 0; i < N; i++) {
174
+ int to_send = sizeof(*at) * (i+1);
175
+
176
+ total_sent_bytes += to_send;
177
+ sent_buffs[i] = at;
178
+ if (send(fds[1], at, to_send, 0) != to_send) {
179
+ if (early_error_started)
180
+ break;
181
+ fprintf(stderr, "send failed %d\n", errno);
182
+ ret = -1;
183
+ goto cleanup;
184
+ }
185
+
186
+ if (i == 2) {
187
+ if (args->early_error == ERROR_EARLY_CLOSE_RECEIVER) {
188
+ /* allow previous sends to complete */
189
+ usleep(1000);
190
+ io_uring_get_events(&ring);
191
+
192
+ sqe = io_uring_get_sqe(&ring);
193
+ io_uring_prep_recv(sqe, fds[0], NULL, 0, 0);
194
+ io_uring_prep_cancel64(sqe, 1234, 0);
195
+ io_uring_sqe_set_data64(sqe, 0x888);
196
+ sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
197
+ io_uring_submit(&ring);
198
+ early_error_started = true;
199
+
200
+ /* allow the cancel to complete */
201
+ usleep(1000);
202
+ io_uring_get_events(&ring);
203
+ }
204
+ if (args->early_error == ERROR_EARLY_CLOSE_SENDER) {
205
+ early_error_started = true;
206
+ shutdown(fds[1], SHUT_RDWR);
207
+ close(fds[1]);
208
+ }
209
+ }
210
+ at += (i+1);
211
+
212
+ if (args->wait_each) {
213
+ ret = io_uring_wait_cqes(&ring, &cqe, 1, &timeout, NULL);
214
+ if (ret) {
215
+ fprintf(stderr, "wait_each failed: %d\n", ret);
216
+ ret = -1;
217
+ goto cleanup;
218
+ }
219
+ while (io_uring_peek_cqe(&ring, &cqe) == 0) {
220
+ recv_cqe[recv_cqes++] = *cqe;
221
+ if (cqe->flags & IORING_CQE_F_MORE) {
222
+ io_uring_cqe_seen(&ring, cqe);
223
+ } else {
224
+ early_error = true;
225
+ io_uring_cqe_seen(&ring, cqe);
226
+ }
227
+ }
228
+ if (early_error)
229
+ break;
230
+ }
231
+ }
232
+
233
+ close(fds[1]);
234
+
235
+ /* allow sends to finish */
236
+ usleep(1000);
237
+
238
+ if ((args->stream && !early_error) || recv_cqes < min_cqes) {
239
+ ret = io_uring_wait_cqes(&ring, &cqe, 1, &timeout, NULL);
240
+ if (ret && ret != -ETIME) {
241
+ fprintf(stderr, "wait final failed: %d\n", ret);
242
+ ret = -1;
243
+ goto cleanup;
244
+ }
245
+ }
246
+
247
+ while (io_uring_peek_cqe(&ring, &cqe) == 0) {
248
+ recv_cqe[recv_cqes++] = *cqe;
249
+ io_uring_cqe_seen(&ring, cqe);
250
+ }
251
+
252
+ ret = -1;
253
+ at = &send_buff[0];
254
+ if (recv_cqes < min_cqes) {
255
+ if (recv_cqes > 0 && recv_cqe[0].res == -EINVAL) {
256
+ return -ENORECVMULTISHOT;
257
+ }
258
+ /* some kernels apparently don't check ->ioprio, skip */
259
+ ret = -ENORECVMULTISHOT;
260
+ goto cleanup;
261
+ }
262
+ for (i = 0; i < recv_cqes; i++) {
263
+ cqe = &recv_cqe[i];
264
+
265
+ bool const is_last = i == recv_cqes - 1;
266
+
267
+ bool const should_be_last =
268
+ (cqe->res <= 0) ||
269
+ (args->stream && is_last) ||
270
+ (args->early_error == ERROR_EARLY_OVERFLOW &&
271
+ !args->wait_each && i == N_CQE_OVERFLOW);
272
+ int *this_recv;
273
+ int orig_payload_size = cqe->res;
274
+
275
+
276
+ if (should_be_last) {
277
+ int used_res = cqe->res;
278
+
279
+ if (!is_last) {
280
+ fprintf(stderr, "not last cqe had error %d\n", i);
281
+ goto cleanup;
282
+ }
283
+
284
+ switch (args->early_error) {
285
+ case ERROR_NOT_ENOUGH_BUFFERS:
286
+ if (cqe->res != -ENOBUFS) {
287
+ fprintf(stderr,
288
+ "ERROR_NOT_ENOUGH_BUFFERS: res %d\n", cqe->res);
289
+ goto cleanup;
290
+ }
291
+ break;
292
+ case ERROR_EARLY_OVERFLOW:
293
+ if (cqe->res < 0) {
294
+ fprintf(stderr,
295
+ "ERROR_EARLY_OVERFLOW: res %d\n", cqe->res);
296
+ goto cleanup;
297
+ }
298
+ break;
299
+ case ERROR_EARLY_CLOSE_RECEIVER:
300
+ if (cqe->res != -ECANCELED) {
301
+ fprintf(stderr,
302
+ "ERROR_EARLY_CLOSE_RECEIVER: res %d\n", cqe->res);
303
+ goto cleanup;
304
+ }
305
+ break;
306
+ case ERROR_NONE:
307
+ case ERROR_EARLY_CLOSE_SENDER:
308
+ if (args->recvmsg && (cqe->flags & IORING_CQE_F_BUFFER)) {
309
+ void *buff = recv_buffs[cqe->flags >> 16];
310
+ struct io_uring_recvmsg_out *o =
311
+ io_uring_recvmsg_validate(buff, cqe->res, &msg);
312
+
313
+ if (!o) {
314
+ fprintf(stderr, "invalid buff\n");
315
+ goto cleanup;
316
+ }
317
+ if (o->payloadlen != 0) {
318
+ fprintf(stderr, "expected 0 payloadlen, got %u\n",
319
+ o->payloadlen);
320
+ goto cleanup;
321
+ }
322
+ used_res = 0;
323
+ } else if (cqe->res != 0) {
324
+ fprintf(stderr, "early error: res %d\n", cqe->res);
325
+ goto cleanup;
326
+ }
327
+ break;
328
+ case ERROR_EARLY_LAST:
329
+ fprintf(stderr, "bad error_early\n");
330
+ goto cleanup;
331
+ };
332
+
333
+ if (cqe->res <= 0 && cqe->flags & IORING_CQE_F_BUFFER) {
334
+ fprintf(stderr, "final BUFFER flag set\n");
335
+ goto cleanup;
336
+ }
337
+
338
+ if (cqe->flags & IORING_CQE_F_MORE) {
339
+ fprintf(stderr, "final MORE flag set\n");
340
+ goto cleanup;
341
+ }
342
+
343
+ if (used_res <= 0)
344
+ continue;
345
+ } else {
346
+ if (!(cqe->flags & IORING_CQE_F_MORE)) {
347
+ fprintf(stderr, "MORE flag not set\n");
348
+ goto cleanup;
349
+ }
350
+ }
351
+
352
+ if (!(cqe->flags & IORING_CQE_F_BUFFER)) {
353
+ fprintf(stderr, "BUFFER flag not set\n");
354
+ goto cleanup;
355
+ }
356
+
357
+ this_recv = recv_buffs[cqe->flags >> 16];
358
+
359
+ if (args->recvmsg) {
360
+ struct io_uring_recvmsg_out *o = io_uring_recvmsg_validate(
361
+ this_recv, cqe->res, &msg);
362
+
363
+ if (!o) {
364
+ fprintf(stderr, "bad recvmsg\n");
365
+ goto cleanup;
366
+ }
367
+ orig_payload_size = o->payloadlen;
368
+
369
+ if (!args->stream) {
370
+ orig_payload_size = o->payloadlen;
371
+
372
+ struct cmsghdr *cmsg;
373
+
374
+ if (o->namelen < sizeof(struct sockaddr_in)) {
375
+ fprintf(stderr, "bad addr len %d",
376
+ o->namelen);
377
+ goto cleanup;
378
+ }
379
+ if (check_sockaddr((struct sockaddr_in *)io_uring_recvmsg_name(o)))
380
+ goto cleanup;
381
+
382
+ cmsg = io_uring_recvmsg_cmsg_firsthdr(o, &msg);
383
+ if (!cmsg ||
384
+ cmsg->cmsg_level != IPPROTO_IP ||
385
+ cmsg->cmsg_type != IP_RECVORIGDSTADDR) {
386
+ fprintf(stderr, "bad cmsg");
387
+ goto cleanup;
388
+ }
389
+ if (check_sockaddr((struct sockaddr_in *)CMSG_DATA(cmsg)))
390
+ goto cleanup;
391
+ cmsg = io_uring_recvmsg_cmsg_nexthdr(o, &msg, cmsg);
392
+ if (cmsg) {
393
+ fprintf(stderr, "unexpected extra cmsg\n");
394
+ goto cleanup;
395
+ }
396
+
397
+ }
398
+
399
+ this_recv = (int *)io_uring_recvmsg_payload(o, &msg);
400
+ cqe->res = io_uring_recvmsg_payload_length(o, cqe->res, &msg);
401
+ if (o->payloadlen != cqe->res) {
402
+ if (!(o->flags & MSG_TRUNC)) {
403
+ fprintf(stderr, "expected truncated flag\n");
404
+ goto cleanup;
405
+ }
406
+ total_dropped_bytes += (o->payloadlen - cqe->res);
407
+ }
408
+ }
409
+
410
+ total_recv_bytes += cqe->res;
411
+
412
+ if (cqe->res % 4 != 0) {
413
+ /*
414
+ * doesn't seem to happen in practice, would need some
415
+ * work to remove this requirement
416
+ */
417
+ fprintf(stderr, "unexpectedly aligned buffer cqe->res=%d\n", cqe->res);
418
+ goto cleanup;
419
+ }
420
+
421
+ /*
422
+ * for tcp: check buffer arrived in order
423
+ * for udp: based on size validate data based on size
424
+ */
425
+ if (!args->stream) {
426
+ int sent_idx = orig_payload_size / sizeof(*at) - 1;
427
+
428
+ if (sent_idx < 0 || sent_idx > N) {
429
+ fprintf(stderr, "Bad sent idx: %d\n", sent_idx);
430
+ goto cleanup;
431
+ }
432
+ at = sent_buffs[sent_idx];
433
+ }
434
+ for (j = 0; j < cqe->res / 4; j++) {
435
+ int sent = *at++;
436
+ int recv = *this_recv++;
437
+
438
+ if (sent != recv) {
439
+ fprintf(stderr, "recv=%d sent=%d\n", recv, sent);
440
+ goto cleanup;
441
+ }
442
+ }
443
+ }
444
+
445
+ if (args->early_error == ERROR_NONE &&
446
+ total_recv_bytes + total_dropped_bytes < total_sent_bytes) {
447
+ fprintf(stderr,
448
+ "missing recv: recv=%d dropped=%d sent=%d\n",
449
+ total_recv_bytes, total_sent_bytes, total_dropped_bytes);
450
+ goto cleanup;
451
+ }
452
+
453
+ ret = 0;
454
+ cleanup:
455
+ for (i = 0; i < ARRAY_SIZE(recv_buffs); i++)
456
+ free(recv_buffs[i]);
457
+ close(fds[0]);
458
+ close(fds[1]);
459
+ io_uring_queue_exit(&ring);
460
+
461
+ return ret;
462
+ }
463
+
464
+ int main(int argc, char *argv[])
465
+ {
466
+ int ret;
467
+ int loop;
468
+ int early_error = 0;
469
+ bool has_defer;
470
+
471
+ if (argc > 1)
472
+ return T_EXIT_SKIP;
473
+
474
+ has_defer = t_probe_defer_taskrun();
475
+
476
+ for (loop = 0; loop < 16; loop++) {
477
+ struct args a = {
478
+ .stream = loop & 0x01,
479
+ .wait_each = loop & 0x2,
480
+ .recvmsg = loop & 0x04,
481
+ .defer = loop & 0x08,
482
+ };
483
+ if (a.defer && !has_defer)
484
+ continue;
485
+ for (early_error = 0; early_error < ERROR_EARLY_LAST; early_error++) {
486
+ a.early_error = (enum early_error_t)early_error;
487
+ ret = test(&a);
488
+ if (ret) {
489
+ if (ret == -ENORECVMULTISHOT) {
490
+ if (loop == 0)
491
+ return T_EXIT_SKIP;
492
+ fprintf(stderr,
493
+ "ENORECVMULTISHOT received but loop>0\n");
494
+ }
495
+ fprintf(stderr,
496
+ "test stream=%d wait_each=%d recvmsg=%d early_error=%d "
497
+ " defer=%d failed\n",
498
+ a.stream, a.wait_each, a.recvmsg, a.early_error, a.defer);
499
+ return T_EXIT_FAIL;
500
+ }
501
+ }
502
+ }
503
+
504
+ return T_EXIT_PASS;
505
+ }
@@ -26,11 +26,8 @@ static int test_rename(struct io_uring *ring, const char *old, const char *new)
26
26
  }
27
27
 
28
28
  memset(sqe, 0, sizeof(*sqe));
29
- sqe->opcode = IORING_OP_RENAMEAT;
30
- sqe->fd = AT_FDCWD;
31
- sqe->addr2 = (unsigned long) new;
32
- sqe->addr = (unsigned long) old;
33
- sqe->len = AT_FDCWD;
29
+
30
+ io_uring_prep_rename(sqe, old, new);
34
31
 
35
32
  ret = io_uring_submit(ring);
36
33
  if (ret <= 0) {
@@ -131,12 +131,97 @@ static int test_iowq_request_cancel(void)
131
131
  ret = read(fds[0], buffer, 10);
132
132
  if (ret < 0)
133
133
  perror("read");
134
+ close(fds[0]);
135
+ return 0;
136
+ }
137
+
138
+ static void trigger_unix_gc(void)
139
+ {
140
+ int fd;
141
+
142
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
143
+ if (fd < 0)
144
+ perror("socket dgram");
145
+ else
146
+ close(fd);
147
+ }
148
+
149
+ static int test_scm_cycles(bool update)
150
+ {
151
+ char buffer[128];
152
+ struct io_uring ring;
153
+ int i, ret;
154
+ int sp[2], fds[2], reg_fds[4];
155
+
156
+ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) {
157
+ perror("Failed to create Unix-domain socket pair\n");
158
+ return 1;
159
+ }
160
+ ret = io_uring_queue_init(8, &ring, 0);
161
+ if (ret < 0) {
162
+ fprintf(stderr, "failed to init io_uring: %s\n", strerror(-ret));
163
+ return ret;
164
+ }
165
+ if (pipe(fds)) {
166
+ perror("pipe");
167
+ return -1;
168
+ }
169
+ send_fd(sp[0], ring.ring_fd);
170
+
171
+ /* register an empty set for updates */
172
+ if (update) {
173
+ for (i = 0; i < 4; i++)
174
+ reg_fds[i] = -1;
175
+ ret = io_uring_register_files(&ring, reg_fds, 4);
176
+ if (ret) {
177
+ fprintf(stderr, "file_register: %d\n", ret);
178
+ return ret;
179
+ }
180
+ }
181
+
182
+ reg_fds[0] = fds[0];
183
+ reg_fds[1] = fds[1];
184
+ reg_fds[2] = sp[0];
185
+ reg_fds[3] = sp[1];
186
+ if (update) {
187
+ ret = io_uring_register_files_update(&ring, 0, reg_fds, 4);
188
+ if (ret != 4) {
189
+ fprintf(stderr, "file_register: %d\n", ret);
190
+ return ret;
191
+ }
192
+ } else {
193
+ ret = io_uring_register_files(&ring, reg_fds, 4);
194
+ if (ret) {
195
+ fprintf(stderr, "file_register: %d\n", ret);
196
+ return ret;
197
+ }
198
+ }
199
+
200
+ close(fds[1]);
201
+ close(sp[0]);
202
+ close(sp[1]);
203
+
204
+ /* should unregister files and close the write fd */
205
+ io_uring_queue_exit(&ring);
206
+
207
+ trigger_unix_gc();
208
+
209
+ /*
210
+ * We're trying to wait for the ring to "really" exit, that will be
211
+ * done async. For that rely on the registered write end to be closed
212
+ * after ring quiesce, so failing read from the other pipe end.
213
+ */
214
+ ret = read(fds[0], buffer, 10);
215
+ if (ret < 0)
216
+ perror("read");
217
+ close(fds[0]);
134
218
  return 0;
135
219
  }
136
220
 
137
221
  int main(int argc, char *argv[])
138
222
  {
139
223
  int sp[2], pid, ring_fd, ret;
224
+ int i;
140
225
 
141
226
  if (argc > 1)
142
227
  return 0;
@@ -147,6 +232,18 @@ int main(int argc, char *argv[])
147
232
  return 1;
148
233
  }
149
234
 
235
+ for (i = 0; i < 2; i++) {
236
+ bool update = !!(i & 1);
237
+
238
+ ret = test_scm_cycles(update);
239
+ if (ret) {
240
+ fprintf(stderr, "test_scm_cycles() failed %i\n",
241
+ update);
242
+ return 1;
243
+ }
244
+ break;
245
+ }
246
+
150
247
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) {
151
248
  perror("Failed to create Unix-domain socket pair\n");
152
249
  return 1;