polyphony 0.84 → 0.86

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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/Gemfile.lock +1 -1
  4. data/Rakefile +1 -1
  5. data/examples/core/multi_suspend.rb +39 -0
  6. data/examples/core/shutdown_all_children.rb +41 -0
  7. data/examples/io/gzip.rb +8 -0
  8. data/examples/io/splice_echo_server.rb +15 -0
  9. data/ext/polyphony/backend_io_uring.c +57 -31
  10. data/ext/polyphony/io_extensions.c +137 -26
  11. data/lib/polyphony/extensions/fiber.rb +3 -1
  12. data/lib/polyphony/extensions/io.rb +4 -0
  13. data/lib/polyphony/extensions/pipe.rb +4 -0
  14. data/lib/polyphony/extensions/socket.rb +4 -0
  15. data/lib/polyphony/version.rb +1 -1
  16. data/polyphony.gemspec +1 -1
  17. data/test/test_backend.rb +1 -1
  18. data/test/test_fiber.rb +5 -2
  19. data/test/test_signal.rb +3 -3
  20. data/vendor/liburing/.github/pull_request_template.md +86 -0
  21. data/vendor/liburing/.github/workflows/build.yml +85 -0
  22. data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
  23. data/vendor/liburing/.gitignore +149 -0
  24. data/vendor/liburing/COPYING +502 -0
  25. data/vendor/liburing/COPYING.GPL +339 -0
  26. data/vendor/liburing/LICENSE +7 -0
  27. data/vendor/liburing/Makefile +82 -0
  28. data/vendor/liburing/Makefile.common +5 -0
  29. data/vendor/liburing/Makefile.quiet +11 -0
  30. data/vendor/liburing/README +46 -0
  31. data/vendor/liburing/configure +486 -0
  32. data/vendor/liburing/debian/README.Debian +7 -0
  33. data/vendor/liburing/debian/changelog +27 -0
  34. data/vendor/liburing/debian/compat +1 -0
  35. data/vendor/liburing/debian/control +48 -0
  36. data/vendor/liburing/debian/copyright +49 -0
  37. data/vendor/liburing/debian/liburing-dev.install +4 -0
  38. data/vendor/liburing/debian/liburing-dev.manpages +6 -0
  39. data/vendor/liburing/debian/liburing1-udeb.install +1 -0
  40. data/vendor/liburing/debian/liburing1.install +1 -0
  41. data/vendor/liburing/debian/liburing1.symbols +32 -0
  42. data/vendor/liburing/debian/patches/series +1 -0
  43. data/vendor/liburing/debian/rules +81 -0
  44. data/vendor/liburing/debian/source/format +1 -0
  45. data/vendor/liburing/debian/source/local-options +2 -0
  46. data/vendor/liburing/debian/source/options +1 -0
  47. data/vendor/liburing/debian/watch +3 -0
  48. data/vendor/liburing/examples/Makefile +38 -0
  49. data/vendor/liburing/examples/io_uring-cp.c +282 -0
  50. data/vendor/liburing/examples/io_uring-test.c +112 -0
  51. data/vendor/liburing/examples/link-cp.c +193 -0
  52. data/vendor/liburing/examples/ucontext-cp.c +273 -0
  53. data/vendor/liburing/liburing.pc.in +12 -0
  54. data/vendor/liburing/liburing.spec +66 -0
  55. data/vendor/liburing/make-debs.sh +53 -0
  56. data/vendor/liburing/man/io_uring.7 +754 -0
  57. data/vendor/liburing/man/io_uring_cq_advance.3 +35 -0
  58. data/vendor/liburing/man/io_uring_cq_ready.3 +25 -0
  59. data/vendor/liburing/man/io_uring_cqe_get_data.3 +34 -0
  60. data/vendor/liburing/man/io_uring_cqe_seen.3 +32 -0
  61. data/vendor/liburing/man/io_uring_enter.2 +1483 -0
  62. data/vendor/liburing/man/io_uring_free_probe.3 +24 -0
  63. data/vendor/liburing/man/io_uring_get_probe.3 +29 -0
  64. data/vendor/liburing/man/io_uring_get_sqe.3 +38 -0
  65. data/vendor/liburing/man/io_uring_opcode_supported.3 +29 -0
  66. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +58 -0
  67. data/vendor/liburing/man/io_uring_prep_read.3 +50 -0
  68. data/vendor/liburing/man/io_uring_prep_read_fixed.3 +54 -0
  69. data/vendor/liburing/man/io_uring_prep_readv.3 +51 -0
  70. data/vendor/liburing/man/io_uring_prep_readv2.3 +79 -0
  71. data/vendor/liburing/man/io_uring_prep_write.3 +50 -0
  72. data/vendor/liburing/man/io_uring_prep_write_fixed.3 +54 -0
  73. data/vendor/liburing/man/io_uring_prep_writev.3 +51 -0
  74. data/vendor/liburing/man/io_uring_prep_writev2.3 +78 -0
  75. data/vendor/liburing/man/io_uring_queue_exit.3 +27 -0
  76. data/vendor/liburing/man/io_uring_queue_init.3 +44 -0
  77. data/vendor/liburing/man/io_uring_register.2 +688 -0
  78. data/vendor/liburing/man/io_uring_register_buffers.3 +41 -0
  79. data/vendor/liburing/man/io_uring_register_files.3 +35 -0
  80. data/vendor/liburing/man/io_uring_setup.2 +534 -0
  81. data/vendor/liburing/man/io_uring_sq_ready.3 +25 -0
  82. data/vendor/liburing/man/io_uring_sq_space_left.3 +25 -0
  83. data/vendor/liburing/man/io_uring_sqe_set_data.3 +30 -0
  84. data/vendor/liburing/man/io_uring_sqe_set_flags.3 +60 -0
  85. data/vendor/liburing/man/io_uring_sqring_wait.3 +30 -0
  86. data/vendor/liburing/man/io_uring_submit.3 +29 -0
  87. data/vendor/liburing/man/io_uring_submit_and_wait.3 +34 -0
  88. data/vendor/liburing/man/io_uring_submit_and_wait_timeout.3 +49 -0
  89. data/vendor/liburing/man/io_uring_unregister_buffers.3 +26 -0
  90. data/vendor/liburing/man/io_uring_unregister_files.3 +26 -0
  91. data/vendor/liburing/man/io_uring_wait_cqe.3 +33 -0
  92. data/vendor/liburing/man/io_uring_wait_cqe_nr.3 +36 -0
  93. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +39 -0
  94. data/vendor/liburing/man/io_uring_wait_cqes.3 +46 -0
  95. data/vendor/liburing/src/Makefile +89 -0
  96. data/vendor/liburing/src/arch/aarch64/syscall.h +95 -0
  97. data/vendor/liburing/src/arch/generic/lib.h +21 -0
  98. data/vendor/liburing/src/arch/generic/syscall.h +87 -0
  99. data/vendor/liburing/src/arch/syscall-defs.h +67 -0
  100. data/vendor/liburing/src/arch/x86/lib.h +32 -0
  101. data/vendor/liburing/src/arch/x86/syscall.h +160 -0
  102. data/vendor/liburing/src/include/liburing/barrier.h +81 -0
  103. data/vendor/liburing/src/include/liburing/io_uring.h +442 -0
  104. data/vendor/liburing/src/include/liburing.h +921 -0
  105. data/vendor/liburing/src/int_flags.h +8 -0
  106. data/vendor/liburing/src/lib.h +57 -0
  107. data/vendor/liburing/src/liburing.map +53 -0
  108. data/vendor/liburing/src/nolibc.c +48 -0
  109. data/vendor/liburing/src/queue.c +403 -0
  110. data/vendor/liburing/src/register.c +293 -0
  111. data/vendor/liburing/src/setup.c +332 -0
  112. data/vendor/liburing/src/syscall.c +47 -0
  113. data/vendor/liburing/src/syscall.h +103 -0
  114. data/vendor/liburing/test/232c93d07b74-test.c +306 -0
  115. data/vendor/liburing/test/35fa71a030ca-test.c +329 -0
  116. data/vendor/liburing/test/500f9fbadef8-test.c +89 -0
  117. data/vendor/liburing/test/7ad0e4b2f83c-test.c +93 -0
  118. data/vendor/liburing/test/8a9973408177-test.c +106 -0
  119. data/vendor/liburing/test/917257daa0fe-test.c +53 -0
  120. data/vendor/liburing/test/Makefile +244 -0
  121. data/vendor/liburing/test/a0908ae19763-test.c +58 -0
  122. data/vendor/liburing/test/a4c0b3decb33-test.c +180 -0
  123. data/vendor/liburing/test/accept-link.c +254 -0
  124. data/vendor/liburing/test/accept-reuse.c +164 -0
  125. data/vendor/liburing/test/accept-test.c +79 -0
  126. data/vendor/liburing/test/accept.c +477 -0
  127. data/vendor/liburing/test/across-fork.c +283 -0
  128. data/vendor/liburing/test/b19062a56726-test.c +53 -0
  129. data/vendor/liburing/test/b5837bd5311d-test.c +77 -0
  130. data/vendor/liburing/test/ce593a6c480a-test.c +136 -0
  131. data/vendor/liburing/test/close-opath.c +122 -0
  132. data/vendor/liburing/test/config +10 -0
  133. data/vendor/liburing/test/connect.c +398 -0
  134. data/vendor/liburing/test/cq-full.c +96 -0
  135. data/vendor/liburing/test/cq-overflow.c +294 -0
  136. data/vendor/liburing/test/cq-peek-batch.c +102 -0
  137. data/vendor/liburing/test/cq-ready.c +94 -0
  138. data/vendor/liburing/test/cq-size.c +64 -0
  139. data/vendor/liburing/test/d4ae271dfaae-test.c +96 -0
  140. data/vendor/liburing/test/d77a67ed5f27-test.c +65 -0
  141. data/vendor/liburing/test/defer.c +307 -0
  142. data/vendor/liburing/test/double-poll-crash.c +185 -0
  143. data/vendor/liburing/test/drop-submit.c +92 -0
  144. data/vendor/liburing/test/eeed8b54e0df-test.c +114 -0
  145. data/vendor/liburing/test/empty-eownerdead.c +45 -0
  146. data/vendor/liburing/test/eventfd-disable.c +151 -0
  147. data/vendor/liburing/test/eventfd-reg.c +76 -0
  148. data/vendor/liburing/test/eventfd-ring.c +97 -0
  149. data/vendor/liburing/test/eventfd.c +112 -0
  150. data/vendor/liburing/test/exec-target.c +6 -0
  151. data/vendor/liburing/test/exit-no-cleanup.c +117 -0
  152. data/vendor/liburing/test/fadvise.c +202 -0
  153. data/vendor/liburing/test/fallocate.c +249 -0
  154. data/vendor/liburing/test/fc2a85cb02ef-test.c +131 -0
  155. data/vendor/liburing/test/file-register.c +858 -0
  156. data/vendor/liburing/test/file-update.c +173 -0
  157. data/vendor/liburing/test/file-verify.c +629 -0
  158. data/vendor/liburing/test/files-exit-hang-poll.c +128 -0
  159. data/vendor/liburing/test/files-exit-hang-timeout.c +134 -0
  160. data/vendor/liburing/test/fixed-link.c +90 -0
  161. data/vendor/liburing/test/fpos.c +252 -0
  162. data/vendor/liburing/test/fsync.c +224 -0
  163. data/vendor/liburing/test/hardlink.c +136 -0
  164. data/vendor/liburing/test/helpers.c +135 -0
  165. data/vendor/liburing/test/helpers.h +67 -0
  166. data/vendor/liburing/test/io-cancel.c +550 -0
  167. data/vendor/liburing/test/io_uring_enter.c +296 -0
  168. data/vendor/liburing/test/io_uring_register.c +676 -0
  169. data/vendor/liburing/test/io_uring_setup.c +192 -0
  170. data/vendor/liburing/test/iopoll.c +372 -0
  171. data/vendor/liburing/test/lfs-openat-write.c +119 -0
  172. data/vendor/liburing/test/lfs-openat.c +275 -0
  173. data/vendor/liburing/test/link-timeout.c +1107 -0
  174. data/vendor/liburing/test/link.c +496 -0
  175. data/vendor/liburing/test/link_drain.c +229 -0
  176. data/vendor/liburing/test/madvise.c +195 -0
  177. data/vendor/liburing/test/mkdir.c +108 -0
  178. data/vendor/liburing/test/msg-ring.c +234 -0
  179. data/vendor/liburing/test/multicqes_drain.c +387 -0
  180. data/vendor/liburing/test/nop-all-sizes.c +99 -0
  181. data/vendor/liburing/test/nop.c +115 -0
  182. data/vendor/liburing/test/open-close.c +261 -0
  183. data/vendor/liburing/test/openat2.c +308 -0
  184. data/vendor/liburing/test/personality.c +204 -0
  185. data/vendor/liburing/test/pipe-eof.c +83 -0
  186. data/vendor/liburing/test/pipe-reuse.c +105 -0
  187. data/vendor/liburing/test/poll-cancel-ton.c +135 -0
  188. data/vendor/liburing/test/poll-cancel.c +228 -0
  189. data/vendor/liburing/test/poll-link.c +230 -0
  190. data/vendor/liburing/test/poll-many.c +208 -0
  191. data/vendor/liburing/test/poll-mshot-update.c +273 -0
  192. data/vendor/liburing/test/poll-ring.c +48 -0
  193. data/vendor/liburing/test/poll-v-poll.c +353 -0
  194. data/vendor/liburing/test/poll.c +109 -0
  195. data/vendor/liburing/test/pollfree.c +426 -0
  196. data/vendor/liburing/test/probe.c +135 -0
  197. data/vendor/liburing/test/read-write.c +876 -0
  198. data/vendor/liburing/test/register-restrictions.c +633 -0
  199. data/vendor/liburing/test/rename.c +135 -0
  200. data/vendor/liburing/test/ring-leak.c +173 -0
  201. data/vendor/liburing/test/ring-leak2.c +249 -0
  202. data/vendor/liburing/test/rsrc_tags.c +449 -0
  203. data/vendor/liburing/test/runtests-loop.sh +16 -0
  204. data/vendor/liburing/test/runtests.sh +170 -0
  205. data/vendor/liburing/test/rw_merge_test.c +97 -0
  206. data/vendor/liburing/test/self.c +91 -0
  207. data/vendor/liburing/test/send_recv.c +286 -0
  208. data/vendor/liburing/test/send_recvmsg.c +345 -0
  209. data/vendor/liburing/test/sendmsg_fs_cve.c +200 -0
  210. data/vendor/liburing/test/shared-wq.c +84 -0
  211. data/vendor/liburing/test/short-read.c +75 -0
  212. data/vendor/liburing/test/shutdown.c +165 -0
  213. data/vendor/liburing/test/sigfd-deadlock.c +74 -0
  214. data/vendor/liburing/test/skip-cqe.c +429 -0
  215. data/vendor/liburing/test/socket-rw-eagain.c +158 -0
  216. data/vendor/liburing/test/socket-rw-offset.c +157 -0
  217. data/vendor/liburing/test/socket-rw.c +145 -0
  218. data/vendor/liburing/test/splice.c +512 -0
  219. data/vendor/liburing/test/sq-full-cpp.cc +45 -0
  220. data/vendor/liburing/test/sq-full.c +45 -0
  221. data/vendor/liburing/test/sq-poll-dup.c +204 -0
  222. data/vendor/liburing/test/sq-poll-kthread.c +169 -0
  223. data/vendor/liburing/test/sq-poll-share.c +137 -0
  224. data/vendor/liburing/test/sq-space_left.c +159 -0
  225. data/vendor/liburing/test/sqpoll-cancel-hang.c +157 -0
  226. data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
  227. data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
  228. data/vendor/liburing/test/sqpoll-sleep.c +69 -0
  229. data/vendor/liburing/test/statx.c +172 -0
  230. data/vendor/liburing/test/stdout.c +232 -0
  231. data/vendor/liburing/test/submit-link-fail.c +154 -0
  232. data/vendor/liburing/test/submit-reuse.c +239 -0
  233. data/vendor/liburing/test/symlink.c +116 -0
  234. data/vendor/liburing/test/teardowns.c +58 -0
  235. data/vendor/liburing/test/thread-exit.c +143 -0
  236. data/vendor/liburing/test/timeout-new.c +252 -0
  237. data/vendor/liburing/test/timeout-overflow.c +204 -0
  238. data/vendor/liburing/test/timeout.c +1523 -0
  239. data/vendor/liburing/test/unlink.c +112 -0
  240. data/vendor/liburing/test/wakeup-hang.c +162 -0
  241. metadata +227 -2
@@ -0,0 +1,165 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Check that writev on a socket that has been shutdown(2) fails
4
+ *
5
+ */
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <stdint.h>
9
+ #include <string.h>
10
+ #include <assert.h>
11
+
12
+ #include <errno.h>
13
+ #include <fcntl.h>
14
+ #include <unistd.h>
15
+ #include <sys/socket.h>
16
+ #include <sys/un.h>
17
+ #include <netinet/tcp.h>
18
+ #include <netinet/in.h>
19
+ #include <arpa/inet.h>
20
+
21
+ #include "liburing.h"
22
+
23
+ static void sig_pipe(int sig)
24
+ {
25
+ }
26
+
27
+ int main(int argc, char *argv[])
28
+ {
29
+ int p_fd[2], ret;
30
+ int32_t recv_s0;
31
+ int32_t val = 1;
32
+ struct sockaddr_in addr;
33
+
34
+ if (argc > 1)
35
+ return 0;
36
+
37
+ srand(getpid());
38
+
39
+ recv_s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
40
+
41
+ ret = setsockopt(recv_s0, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
42
+ assert(ret != -1);
43
+ ret = setsockopt(recv_s0, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
44
+ assert(ret != -1);
45
+
46
+ addr.sin_family = AF_INET;
47
+ addr.sin_port = htons((rand() % 61440) + 4096);
48
+ addr.sin_addr.s_addr = inet_addr("127.0.0.1");
49
+
50
+ ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr));
51
+ assert(ret != -1);
52
+ ret = listen(recv_s0, 128);
53
+ assert(ret != -1);
54
+
55
+ p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
56
+
57
+ val = 1;
58
+ ret = setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
59
+ assert(ret != -1);
60
+
61
+ int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
62
+ assert(flags != -1);
63
+
64
+ flags |= O_NONBLOCK;
65
+ ret = fcntl(p_fd[1], F_SETFL, flags);
66
+ assert(ret != -1);
67
+
68
+ ret = connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr));
69
+ assert(ret == -1);
70
+
71
+ flags = fcntl(p_fd[1], F_GETFL, 0);
72
+ assert(flags != -1);
73
+
74
+ flags &= ~O_NONBLOCK;
75
+ ret = fcntl(p_fd[1], F_SETFL, flags);
76
+ assert(ret != -1);
77
+
78
+ p_fd[0] = accept(recv_s0, NULL, NULL);
79
+ assert(p_fd[0] != -1);
80
+
81
+ signal(SIGPIPE, sig_pipe);
82
+
83
+ while (1) {
84
+ int32_t code;
85
+ socklen_t code_len = sizeof(code);
86
+
87
+ ret = getsockopt(p_fd[1], SOL_SOCKET, SO_ERROR, &code, &code_len);
88
+ assert(ret != -1);
89
+
90
+ if (!code)
91
+ break;
92
+ }
93
+
94
+ struct io_uring m_io_uring;
95
+
96
+ ret = io_uring_queue_init(32, &m_io_uring, 0);
97
+ assert(ret >= 0);
98
+
99
+ {
100
+ struct io_uring_cqe *cqe;
101
+ struct io_uring_sqe *sqe;
102
+ int res;
103
+
104
+ sqe = io_uring_get_sqe(&m_io_uring);
105
+ io_uring_prep_shutdown(sqe, p_fd[1], SHUT_WR);
106
+ sqe->user_data = 1;
107
+
108
+ res = io_uring_submit_and_wait(&m_io_uring, 1);
109
+ assert(res != -1);
110
+
111
+ res = io_uring_wait_cqe(&m_io_uring, &cqe);
112
+ if (res < 0) {
113
+ fprintf(stderr, "wait: %s\n", strerror(-ret));
114
+ goto err;
115
+ }
116
+
117
+ if (cqe->res) {
118
+ if (cqe->res == -EINVAL) {
119
+ fprintf(stdout, "Shutdown not supported, skipping\n");
120
+ goto done;
121
+ }
122
+ fprintf(stderr, "writev: %d\n", cqe->res);
123
+ goto err;
124
+ }
125
+
126
+ io_uring_cqe_seen(&m_io_uring, cqe);
127
+ }
128
+
129
+ {
130
+ struct io_uring_cqe *cqe;
131
+ struct io_uring_sqe *sqe;
132
+ struct iovec iov[1];
133
+ char send_buff[128];
134
+ int res;
135
+
136
+ iov[0].iov_base = send_buff;
137
+ iov[0].iov_len = sizeof(send_buff);
138
+
139
+ sqe = io_uring_get_sqe(&m_io_uring);
140
+ assert(sqe != NULL);
141
+
142
+ io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0);
143
+ res = io_uring_submit_and_wait(&m_io_uring, 1);
144
+ assert(res != -1);
145
+
146
+ res = io_uring_wait_cqe(&m_io_uring, &cqe);
147
+ if (res < 0) {
148
+ fprintf(stderr, "wait: %s\n", strerror(-ret));
149
+ goto err;
150
+ }
151
+
152
+ if (cqe->res != -EPIPE) {
153
+ fprintf(stderr, "writev: %d\n", cqe->res);
154
+ goto err;
155
+ }
156
+ io_uring_cqe_seen(&m_io_uring, cqe);
157
+ }
158
+
159
+ done:
160
+ io_uring_queue_exit(&m_io_uring);
161
+ return 0;
162
+ err:
163
+ io_uring_queue_exit(&m_io_uring);
164
+ return 1;
165
+ }
@@ -0,0 +1,74 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: test that sigfd reading/polling works. A regression test for
4
+ * the upstream commit:
5
+ *
6
+ * fd7d6de22414 ("io_uring: don't recurse on tsk->sighand->siglock with signalfd")
7
+ */
8
+ #include <unistd.h>
9
+ #include <sys/signalfd.h>
10
+ #include <sys/epoll.h>
11
+ #include <poll.h>
12
+ #include <stdio.h>
13
+ #include "liburing.h"
14
+
15
+ static int setup_signal(void)
16
+ {
17
+ sigset_t mask;
18
+ int sfd;
19
+
20
+ sigemptyset(&mask);
21
+ sigaddset(&mask, SIGINT);
22
+
23
+ sigprocmask(SIG_BLOCK, &mask, NULL);
24
+ sfd = signalfd(-1, &mask, SFD_NONBLOCK);
25
+ if (sfd < 0)
26
+ perror("signalfd");
27
+ return sfd;
28
+ }
29
+
30
+ static int test_uring(int sfd)
31
+ {
32
+ struct io_uring_sqe *sqe;
33
+ struct io_uring_cqe *cqe;
34
+ struct io_uring ring;
35
+ int ret;
36
+
37
+ io_uring_queue_init(32, &ring, 0);
38
+
39
+ sqe = io_uring_get_sqe(&ring);
40
+ io_uring_prep_poll_add(sqe, sfd, POLLIN);
41
+ io_uring_submit(&ring);
42
+
43
+ kill(getpid(), SIGINT);
44
+
45
+ io_uring_wait_cqe(&ring, &cqe);
46
+ if (cqe->res & POLLIN) {
47
+ ret = 0;
48
+ } else {
49
+ fprintf(stderr, "Unexpected poll mask %x\n", cqe->res);
50
+ ret = 1;
51
+ }
52
+ io_uring_cqe_seen(&ring, cqe);
53
+ io_uring_queue_exit(&ring);
54
+ return ret;
55
+ }
56
+
57
+ int main(int argc, char *argv[])
58
+ {
59
+ int sfd, ret;
60
+
61
+ if (argc > 1)
62
+ return 0;
63
+
64
+ sfd = setup_signal();
65
+ if (sfd < 0)
66
+ return 1;
67
+
68
+ ret = test_uring(sfd);
69
+ if (ret)
70
+ fprintf(stderr, "test_uring signalfd failed\n");
71
+
72
+ close(sfd);
73
+ return ret;
74
+ }
@@ -0,0 +1,429 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <unistd.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <fcntl.h>
8
+ #include <assert.h>
9
+
10
+ #include "liburing.h"
11
+
12
+ #define LINK_SIZE 6
13
+ #define TIMEOUT_USER_DATA (-1)
14
+
15
+ static int fds[2];
16
+
17
+ /* should be successfully submitted but fails during execution */
18
+ static void prep_exec_fail_req(struct io_uring_sqe *sqe)
19
+ {
20
+ io_uring_prep_write(sqe, fds[1], NULL, 100, 0);
21
+ }
22
+
23
+ static int test_link_success(struct io_uring *ring, int nr, bool skip_last)
24
+ {
25
+ struct io_uring_cqe *cqe;
26
+ struct io_uring_sqe *sqe;
27
+ int ret, i;
28
+
29
+ for (i = 0; i < nr; ++i) {
30
+ sqe = io_uring_get_sqe(ring);
31
+ io_uring_prep_nop(sqe);
32
+ if (i != nr - 1 || skip_last)
33
+ sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
34
+ sqe->user_data = i;
35
+ }
36
+
37
+ ret = io_uring_submit(ring);
38
+ if (ret != nr) {
39
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
40
+ goto err;
41
+ }
42
+
43
+ if (!skip_last) {
44
+ ret = io_uring_wait_cqe(ring, &cqe);
45
+ if (ret != 0) {
46
+ fprintf(stderr, "wait completion %d\n", ret);
47
+ goto err;
48
+ }
49
+ if (cqe->res != 0) {
50
+ fprintf(stderr, "nop failed: res %d\n", cqe->res);
51
+ goto err;
52
+ }
53
+ if (cqe->user_data != nr - 1) {
54
+ fprintf(stderr, "invalid user_data %i\n", (int)cqe->user_data);
55
+ goto err;
56
+ }
57
+ io_uring_cqe_seen(ring, cqe);
58
+ }
59
+
60
+ if (io_uring_peek_cqe(ring, &cqe) >= 0) {
61
+ fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
62
+ goto err;
63
+ }
64
+ return 0;
65
+ err:
66
+ return 1;
67
+ }
68
+
69
+ static int test_link_fail(struct io_uring *ring, int nr, int fail_idx)
70
+ {
71
+ struct io_uring_cqe *cqe;
72
+ struct io_uring_sqe *sqe;
73
+ int ret, i;
74
+
75
+ for (i = 0; i < nr; ++i) {
76
+ sqe = io_uring_get_sqe(ring);
77
+ if (i == fail_idx)
78
+ prep_exec_fail_req(sqe);
79
+ else
80
+ io_uring_prep_nop(sqe);
81
+
82
+ if (i != nr - 1)
83
+ sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
84
+ sqe->user_data = i;
85
+ }
86
+
87
+ ret = io_uring_submit(ring);
88
+ if (ret != nr) {
89
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
90
+ goto err;
91
+ }
92
+ ret = io_uring_wait_cqe(ring, &cqe);
93
+ if (ret != 0) {
94
+ fprintf(stderr, "wait completion %d\n", ret);
95
+ goto err;
96
+ }
97
+ if (!cqe->res || cqe->user_data != fail_idx) {
98
+ fprintf(stderr, "got: user_data %d res %d, expected data: %d\n",
99
+ (int)cqe->user_data, cqe->res, fail_idx);
100
+ goto err;
101
+ }
102
+ io_uring_cqe_seen(ring, cqe);
103
+
104
+ if (io_uring_peek_cqe(ring, &cqe) >= 0) {
105
+ fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
106
+ goto err;
107
+ }
108
+ return 0;
109
+ err:
110
+ return 1;
111
+ }
112
+
113
+ static int test_ltimeout_cancel(struct io_uring *ring, int nr, int tout_idx,
114
+ bool async, int fail_idx)
115
+ {
116
+ struct __kernel_timespec ts = {.tv_sec = 1, .tv_nsec = 0};
117
+ struct io_uring_cqe *cqe;
118
+ struct io_uring_sqe *sqe;
119
+ int ret, i;
120
+ int e_res = 0, e_idx = nr - 1;
121
+
122
+ if (fail_idx >= 0) {
123
+ e_res = -EFAULT;
124
+ e_idx = fail_idx;
125
+ }
126
+
127
+ for (i = 0; i < nr; ++i) {
128
+ sqe = io_uring_get_sqe(ring);
129
+ if (i == fail_idx)
130
+ prep_exec_fail_req(sqe);
131
+ else
132
+ io_uring_prep_nop(sqe);
133
+ sqe->user_data = i;
134
+ sqe->flags |= IOSQE_IO_LINK;
135
+ if (async)
136
+ sqe->flags |= IOSQE_ASYNC;
137
+ if (i != nr - 1)
138
+ sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
139
+
140
+ if (i == tout_idx) {
141
+ sqe = io_uring_get_sqe(ring);
142
+ io_uring_prep_link_timeout(sqe, &ts, 0);
143
+ sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
144
+ sqe->user_data = TIMEOUT_USER_DATA;
145
+ }
146
+ }
147
+
148
+ ret = io_uring_submit(ring);
149
+ if (ret != nr + 1) {
150
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
151
+ goto err;
152
+ }
153
+ ret = io_uring_wait_cqe(ring, &cqe);
154
+ if (ret != 0) {
155
+ fprintf(stderr, "wait completion %d\n", ret);
156
+ goto err;
157
+ }
158
+ if (cqe->user_data != e_idx) {
159
+ fprintf(stderr, "invalid user_data %i\n", (int)cqe->user_data);
160
+ goto err;
161
+ }
162
+ if (cqe->res != e_res) {
163
+ fprintf(stderr, "unexpected res: %d\n", cqe->res);
164
+ goto err;
165
+ }
166
+ io_uring_cqe_seen(ring, cqe);
167
+
168
+ if (io_uring_peek_cqe(ring, &cqe) >= 0) {
169
+ fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
170
+ goto err;
171
+ }
172
+ return 0;
173
+ err:
174
+ return 1;
175
+ }
176
+
177
+ static int test_ltimeout_fire(struct io_uring *ring, bool async,
178
+ bool skip_main, bool skip_tout)
179
+ {
180
+ char buf[1];
181
+ struct __kernel_timespec ts = {.tv_sec = 0, .tv_nsec = 1000000};
182
+ struct io_uring_cqe *cqe;
183
+ struct io_uring_sqe *sqe;
184
+ int ret, i;
185
+ int nr = 1 + !skip_tout;
186
+
187
+ sqe = io_uring_get_sqe(ring);
188
+ io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
189
+ sqe->flags |= IOSQE_IO_LINK;
190
+ sqe->flags |= async ? IOSQE_ASYNC : 0;
191
+ sqe->flags |= skip_main ? IOSQE_CQE_SKIP_SUCCESS : 0;
192
+ sqe->user_data = 0;
193
+
194
+ sqe = io_uring_get_sqe(ring);
195
+ io_uring_prep_link_timeout(sqe, &ts, 0);
196
+ sqe->flags |= skip_tout ? IOSQE_CQE_SKIP_SUCCESS : 0;
197
+ sqe->user_data = 1;
198
+
199
+ ret = io_uring_submit(ring);
200
+ if (ret != 2) {
201
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
202
+ return 1;
203
+ }
204
+
205
+ for (i = 0; i < nr; i++) {
206
+ ret = io_uring_wait_cqe(ring, &cqe);
207
+ if (ret != 0) {
208
+ fprintf(stderr, "wait completion %d\n", ret);
209
+ return 1;
210
+ }
211
+ switch (cqe->user_data) {
212
+ case 0:
213
+ if (cqe->res != -ECANCELED && cqe->res != -EINTR) {
214
+ fprintf(stderr, "unexpected read return: %d\n", cqe->res);
215
+ return 1;
216
+ }
217
+ break;
218
+ case 1:
219
+ if (skip_tout) {
220
+ fprintf(stderr, "extra timeout cqe, %d\n", cqe->res);
221
+ return 1;
222
+ }
223
+ break;
224
+ }
225
+ io_uring_cqe_seen(ring, cqe);
226
+ }
227
+
228
+
229
+ if (io_uring_peek_cqe(ring, &cqe) >= 0) {
230
+ fprintf(stderr, "single CQE expected: got data: %i res: %i\n",
231
+ (int)cqe->user_data, cqe->res);
232
+ return 1;
233
+ }
234
+ return 0;
235
+ }
236
+
237
+ static int test_hardlink(struct io_uring *ring, int nr, int fail_idx,
238
+ int skip_idx, bool hardlink_last)
239
+ {
240
+ struct io_uring_cqe *cqe;
241
+ struct io_uring_sqe *sqe;
242
+ int ret, i;
243
+
244
+ assert(fail_idx < nr);
245
+ assert(skip_idx < nr);
246
+
247
+ for (i = 0; i < nr; i++) {
248
+ sqe = io_uring_get_sqe(ring);
249
+ if (i == fail_idx)
250
+ prep_exec_fail_req(sqe);
251
+ else
252
+ io_uring_prep_nop(sqe);
253
+ if (i != nr - 1 || hardlink_last)
254
+ sqe->flags |= IOSQE_IO_HARDLINK;
255
+ if (i == skip_idx)
256
+ sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
257
+ sqe->user_data = i;
258
+ }
259
+
260
+ ret = io_uring_submit(ring);
261
+ if (ret != nr) {
262
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
263
+ goto err;
264
+ }
265
+
266
+ for (i = 0; i < nr; i++) {
267
+ if (i == skip_idx && fail_idx != skip_idx)
268
+ continue;
269
+
270
+ ret = io_uring_wait_cqe(ring, &cqe);
271
+ if (ret != 0) {
272
+ fprintf(stderr, "wait completion %d\n", ret);
273
+ goto err;
274
+ }
275
+ if (cqe->user_data != i) {
276
+ fprintf(stderr, "invalid user_data %d (%i)\n",
277
+ (int)cqe->user_data, i);
278
+ goto err;
279
+ }
280
+ if (i == fail_idx) {
281
+ if (cqe->res >= 0) {
282
+ fprintf(stderr, "req should've failed %d %d\n",
283
+ (int)cqe->user_data, cqe->res);
284
+ goto err;
285
+ }
286
+ } else {
287
+ if (cqe->res) {
288
+ fprintf(stderr, "req error %d %d\n",
289
+ (int)cqe->user_data, cqe->res);
290
+ goto err;
291
+ }
292
+ }
293
+
294
+ io_uring_cqe_seen(ring, cqe);
295
+ }
296
+
297
+ if (io_uring_peek_cqe(ring, &cqe) >= 0) {
298
+ fprintf(stderr, "single CQE expected %i\n", (int)cqe->user_data);
299
+ goto err;
300
+ }
301
+ return 0;
302
+ err:
303
+ return 1;
304
+ }
305
+
306
+ int main(int argc, char *argv[])
307
+ {
308
+ struct io_uring ring;
309
+ int ret, i, j, k;
310
+ int mid_idx = LINK_SIZE / 2;
311
+ int last_idx = LINK_SIZE - 1;
312
+
313
+ if (argc > 1)
314
+ return 0;
315
+
316
+ if (pipe(fds)) {
317
+ fprintf(stderr, "pipe() failed\n");
318
+ return 1;
319
+ }
320
+ ret = io_uring_queue_init(16, &ring, 0);
321
+ if (ret) {
322
+ fprintf(stderr, "ring setup failed: %d\n", ret);
323
+ return 1;
324
+ }
325
+
326
+ if (!(ring.features & IORING_FEAT_CQE_SKIP)) {
327
+ printf("IOSQE_CQE_SKIP_SUCCESS is not supported, skip\n");
328
+ return 0;
329
+ }
330
+
331
+ for (i = 0; i < 4; i++) {
332
+ bool skip_last = i & 1;
333
+ int sz = (i & 2) ? LINK_SIZE : 1;
334
+
335
+ ret = test_link_success(&ring, sz, skip_last);
336
+ if (ret) {
337
+ fprintf(stderr, "test_link_success sz %d, %d last\n",
338
+ skip_last, sz);
339
+ return ret;
340
+ }
341
+ }
342
+
343
+ ret = test_link_fail(&ring, LINK_SIZE, mid_idx);
344
+ if (ret) {
345
+ fprintf(stderr, "test_link_fail mid failed\n");
346
+ return ret;
347
+ }
348
+
349
+ ret = test_link_fail(&ring, LINK_SIZE, last_idx);
350
+ if (ret) {
351
+ fprintf(stderr, "test_link_fail last failed\n");
352
+ return ret;
353
+ }
354
+
355
+ for (i = 0; i < 2; i++) {
356
+ bool async = i & 1;
357
+
358
+ ret = test_ltimeout_cancel(&ring, 1, 0, async, -1);
359
+ if (ret) {
360
+ fprintf(stderr, "test_ltimeout_cancel 1 failed, %i\n",
361
+ async);
362
+ return ret;
363
+ }
364
+ ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, -1);
365
+ if (ret) {
366
+ fprintf(stderr, "test_ltimeout_cancel mid failed, %i\n",
367
+ async);
368
+ return ret;
369
+ }
370
+ ret = test_ltimeout_cancel(&ring, LINK_SIZE, last_idx, async, -1);
371
+ if (ret) {
372
+ fprintf(stderr, "test_ltimeout_cancel last failed, %i\n",
373
+ async);
374
+ return ret;
375
+ }
376
+ ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx);
377
+ if (ret) {
378
+ fprintf(stderr, "test_ltimeout_cancel fail mid failed, %i\n",
379
+ async);
380
+ return ret;
381
+ }
382
+ ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx - 1);
383
+ if (ret) {
384
+ fprintf(stderr, "test_ltimeout_cancel fail2 mid failed, %i\n",
385
+ async);
386
+ return ret;
387
+ }
388
+ ret = test_ltimeout_cancel(&ring, LINK_SIZE, mid_idx, async, mid_idx + 1);
389
+ if (ret) {
390
+ fprintf(stderr, "test_ltimeout_cancel fail3 mid failed, %i\n",
391
+ async);
392
+ return ret;
393
+ }
394
+ }
395
+
396
+ for (i = 0; i < 8; i++) {
397
+ bool async = i & 1;
398
+ bool skip1 = i & 2;
399
+ bool skip2 = i & 4;
400
+
401
+ ret = test_ltimeout_fire(&ring, async, skip1, skip2);
402
+ if (ret) {
403
+ fprintf(stderr, "test_ltimeout_fire failed\n");
404
+ return ret;
405
+ }
406
+ }
407
+
408
+ /* test 3 positions, start/middle/end of the link, i.e. indexes 0, 3, 6 */
409
+ for (i = 0; i < 3; i++) {
410
+ for (j = 0; j < 3; j++) {
411
+ for (k = 0; k < 2; k++) {
412
+ bool mark_last = k & 1;
413
+
414
+ ret = test_hardlink(&ring, 7, i * 3, j * 3, mark_last);
415
+ if (ret) {
416
+ fprintf(stderr, "test_hardlink failed"
417
+ "fail %i skip %i mark last %i\n",
418
+ i * 3, j * 3, k);
419
+ return 1;
420
+ }
421
+ }
422
+ }
423
+ }
424
+
425
+ close(fds[0]);
426
+ close(fds[1]);
427
+ io_uring_queue_exit(&ring);
428
+ return 0;
429
+ }