polyphony 0.98 → 0.99.1

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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -1
  3. data/.rubocop.yml +3 -3
  4. data/.yardopts +30 -0
  5. data/CHANGELOG.md +11 -0
  6. data/LICENSE +1 -1
  7. data/README.md +63 -29
  8. data/Rakefile +1 -5
  9. data/TODO.md +0 -4
  10. data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
  11. data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
  12. data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
  13. data/docs/{main-concepts/extending.md → extending.md} +2 -9
  14. data/docs/faq.md +3 -16
  15. data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
  16. data/docs/link_rewriter.rb +16 -0
  17. data/docs/{getting-started/overview.md → overview.md} +1 -30
  18. data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
  19. data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
  20. data/examples/adapters/redis_client.rb +3 -2
  21. data/examples/io/echo_server.rb +1 -1
  22. data/examples/io/echo_server_plain_ruby.rb +26 -0
  23. data/examples/io/https_server_sni_2.rb +14 -8
  24. data/ext/polyphony/backend_io_uring.c +154 -9
  25. data/ext/polyphony/backend_io_uring_context.c +21 -12
  26. data/ext/polyphony/backend_io_uring_context.h +12 -7
  27. data/ext/polyphony/backend_libev.c +1 -1
  28. data/ext/polyphony/extconf.rb +25 -8
  29. data/ext/polyphony/fiber.c +79 -2
  30. data/ext/polyphony/io_extensions.c +53 -0
  31. data/ext/polyphony/libev.h +0 -2
  32. data/ext/polyphony/pipe.c +42 -2
  33. data/ext/polyphony/polyphony.c +345 -31
  34. data/ext/polyphony/polyphony.h +9 -2
  35. data/ext/polyphony/queue.c +181 -0
  36. data/ext/polyphony/ring_buffer.c +0 -1
  37. data/ext/polyphony/runqueue.c +8 -1
  38. data/ext/polyphony/runqueue_ring_buffer.c +13 -0
  39. data/ext/polyphony/runqueue_ring_buffer.h +2 -1
  40. data/ext/polyphony/socket_extensions.c +6 -0
  41. data/ext/polyphony/thread.c +34 -2
  42. data/lib/polyphony/adapters/process.rb +11 -1
  43. data/lib/polyphony/adapters/sequel.rb +1 -1
  44. data/lib/polyphony/core/channel.rb +2 -0
  45. data/lib/polyphony/core/debug.rb +1 -1
  46. data/lib/polyphony/core/global_api.rb +25 -24
  47. data/lib/polyphony/core/resource_pool.rb +7 -6
  48. data/lib/polyphony/core/sync.rb +55 -2
  49. data/lib/polyphony/core/thread_pool.rb +3 -3
  50. data/lib/polyphony/core/timer.rb +8 -8
  51. data/lib/polyphony/extensions/exception.rb +2 -0
  52. data/lib/polyphony/extensions/fiber.rb +15 -13
  53. data/lib/polyphony/extensions/io.rb +161 -16
  54. data/lib/polyphony/extensions/kernel.rb +20 -2
  55. data/lib/polyphony/extensions/openssl.rb +101 -12
  56. data/lib/polyphony/extensions/pipe.rb +103 -7
  57. data/lib/polyphony/extensions/process.rb +13 -1
  58. data/lib/polyphony/extensions/socket.rb +93 -27
  59. data/lib/polyphony/extensions/thread.rb +9 -1
  60. data/lib/polyphony/extensions/timeout.rb +1 -1
  61. data/lib/polyphony/version.rb +2 -1
  62. data/lib/polyphony.rb +27 -7
  63. data/polyphony.gemspec +1 -8
  64. data/test/stress.rb +1 -1
  65. data/test/test_global_api.rb +45 -7
  66. data/test/test_io.rb +6 -7
  67. data/test/test_socket.rb +157 -0
  68. data/test/test_sync.rb +42 -1
  69. data/test/test_timer.rb +5 -5
  70. data/vendor/liburing/.github/workflows/build.yml +7 -16
  71. data/vendor/liburing/.gitignore +5 -0
  72. data/vendor/liburing/CHANGELOG +23 -1
  73. data/vendor/liburing/Makefile +4 -3
  74. data/vendor/liburing/Makefile.common +1 -0
  75. data/vendor/liburing/README +48 -0
  76. data/vendor/liburing/configure +76 -6
  77. data/vendor/liburing/debian/changelog +11 -0
  78. data/vendor/liburing/debian/control +7 -16
  79. data/vendor/liburing/debian/liburing-dev.manpages +3 -6
  80. data/vendor/liburing/debian/liburing2.install +1 -0
  81. data/vendor/liburing/debian/liburing2.symbols +56 -0
  82. data/vendor/liburing/debian/rules +15 -68
  83. data/vendor/liburing/examples/Makefile +4 -0
  84. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  85. data/vendor/liburing/examples/io_uring-udp.c +1 -1
  86. data/vendor/liburing/examples/send-zerocopy.c +315 -56
  87. data/vendor/liburing/examples/ucontext-cp.c +2 -17
  88. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  89. data/vendor/liburing/liburing.pc.in +1 -1
  90. data/vendor/liburing/liburing.spec +1 -1
  91. data/vendor/liburing/make-debs.sh +3 -3
  92. data/vendor/liburing/man/IO_URING_CHECK_VERSION.3 +1 -0
  93. data/vendor/liburing/man/IO_URING_VERSION_MAJOR.3 +1 -0
  94. data/vendor/liburing/man/IO_URING_VERSION_MINOR.3 +1 -0
  95. data/vendor/liburing/man/io_uring_buf_ring_add.3 +6 -6
  96. data/vendor/liburing/man/io_uring_check_version.3 +72 -0
  97. data/vendor/liburing/man/io_uring_close_ring_fd.3 +43 -0
  98. data/vendor/liburing/man/io_uring_major_version.3 +1 -0
  99. data/vendor/liburing/man/io_uring_minor_version.3 +1 -0
  100. data/vendor/liburing/man/io_uring_prep_accept.3 +1 -1
  101. data/vendor/liburing/man/io_uring_prep_fgetxattr.3 +1 -0
  102. data/vendor/liburing/man/io_uring_prep_fsetxattr.3 +1 -0
  103. data/vendor/liburing/man/io_uring_prep_getxattr.3 +61 -0
  104. data/vendor/liburing/man/io_uring_prep_link_timeout.3 +94 -0
  105. data/vendor/liburing/man/io_uring_prep_msg_ring.3 +22 -2
  106. data/vendor/liburing/man/io_uring_prep_msg_ring_cqe_flags.3 +1 -0
  107. data/vendor/liburing/man/io_uring_prep_poll_add.3 +1 -1
  108. data/vendor/liburing/man/io_uring_prep_provide_buffers.3 +18 -9
  109. data/vendor/liburing/man/io_uring_prep_readv.3 +3 -3
  110. data/vendor/liburing/man/io_uring_prep_readv2.3 +3 -3
  111. data/vendor/liburing/man/io_uring_prep_recv.3 +5 -5
  112. data/vendor/liburing/man/io_uring_prep_recvmsg.3 +4 -4
  113. data/vendor/liburing/man/io_uring_prep_send.3 +9 -0
  114. data/vendor/liburing/man/io_uring_prep_send_set_addr.3 +38 -0
  115. data/vendor/liburing/man/io_uring_prep_send_zc.3 +39 -7
  116. data/vendor/liburing/man/io_uring_prep_send_zc_fixed.3 +1 -0
  117. data/vendor/liburing/man/io_uring_prep_sendmsg.3 +20 -0
  118. data/vendor/liburing/man/io_uring_prep_sendmsg_zc.3 +1 -0
  119. data/vendor/liburing/man/io_uring_prep_setxattr.3 +64 -0
  120. data/vendor/liburing/man/io_uring_prep_splice.3 +40 -0
  121. data/vendor/liburing/man/io_uring_prep_writev.3 +2 -2
  122. data/vendor/liburing/man/io_uring_prep_writev2.3 +2 -2
  123. data/vendor/liburing/man/io_uring_recvmsg_out.3 +13 -9
  124. data/vendor/liburing/man/io_uring_register.2 +15 -9
  125. data/vendor/liburing/man/io_uring_register_buf_ring.3 +4 -4
  126. data/vendor/liburing/man/io_uring_register_buffers.3 +49 -6
  127. data/vendor/liburing/man/io_uring_register_buffers_sparse.3 +1 -0
  128. data/vendor/liburing/man/io_uring_register_buffers_tags.3 +1 -0
  129. data/vendor/liburing/man/io_uring_register_buffers_update_tag.3 +1 -0
  130. data/vendor/liburing/man/io_uring_register_files.3 +60 -5
  131. data/vendor/liburing/man/io_uring_register_files_tags.3 +1 -0
  132. data/vendor/liburing/man/io_uring_register_files_update.3 +1 -0
  133. data/vendor/liburing/man/io_uring_register_files_update_tag.3 +1 -0
  134. data/vendor/liburing/man/io_uring_setup.2 +31 -2
  135. data/vendor/liburing/man/io_uring_wait_cqe_timeout.3 +1 -1
  136. data/vendor/liburing/src/Makefile +25 -3
  137. data/vendor/liburing/src/ffi.c +15 -0
  138. data/vendor/liburing/src/include/liburing/io_uring.h +30 -7
  139. data/vendor/liburing/src/include/liburing.h +190 -148
  140. data/vendor/liburing/src/int_flags.h +1 -0
  141. data/vendor/liburing/src/lib.h +5 -16
  142. data/vendor/liburing/src/liburing-ffi.map +172 -0
  143. data/vendor/liburing/src/liburing.map +11 -0
  144. data/vendor/liburing/src/nolibc.c +9 -2
  145. data/vendor/liburing/src/queue.c +2 -2
  146. data/vendor/liburing/src/register.c +66 -96
  147. data/vendor/liburing/src/setup.c +5 -4
  148. data/vendor/liburing/src/version.c +21 -0
  149. data/vendor/liburing/test/232c93d07b74.c +3 -3
  150. data/vendor/liburing/test/35fa71a030ca.c +3 -3
  151. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  152. data/vendor/liburing/test/917257daa0fe.c +1 -1
  153. data/vendor/liburing/test/Makefile +27 -7
  154. data/vendor/liburing/test/a0908ae19763.c +2 -2
  155. data/vendor/liburing/test/a4c0b3decb33.c +2 -2
  156. data/vendor/liburing/test/accept-link.c +4 -4
  157. data/vendor/liburing/test/accept-reuse.c +5 -7
  158. data/vendor/liburing/test/accept.c +34 -31
  159. data/vendor/liburing/test/b19062a56726.c +1 -1
  160. data/vendor/liburing/test/buf-ring.c +58 -4
  161. data/vendor/liburing/test/ce593a6c480a.c +2 -2
  162. data/vendor/liburing/test/close-opath.c +2 -1
  163. data/vendor/liburing/test/connect.c +8 -0
  164. data/vendor/liburing/test/cq-overflow.c +14 -8
  165. data/vendor/liburing/test/d4ae271dfaae.c +1 -1
  166. data/vendor/liburing/test/defer-taskrun.c +64 -9
  167. data/vendor/liburing/test/defer.c +1 -1
  168. data/vendor/liburing/test/double-poll-crash.c +3 -3
  169. data/vendor/liburing/test/eeed8b54e0df.c +8 -3
  170. data/vendor/liburing/test/eploop.c +74 -0
  171. data/vendor/liburing/test/eventfd-ring.c +1 -1
  172. data/vendor/liburing/test/eventfd.c +1 -1
  173. data/vendor/liburing/test/evloop.c +73 -0
  174. data/vendor/liburing/test/exit-no-cleanup.c +1 -1
  175. data/vendor/liburing/test/fadvise.c +1 -1
  176. data/vendor/liburing/test/fc2a85cb02ef.c +3 -3
  177. data/vendor/liburing/test/fd-pass.c +35 -16
  178. data/vendor/liburing/test/file-register.c +61 -0
  179. data/vendor/liburing/test/file-verify.c +2 -2
  180. data/vendor/liburing/test/files-exit-hang-timeout.c +2 -2
  181. data/vendor/liburing/test/fixed-link.c +1 -1
  182. data/vendor/liburing/test/fsnotify.c +118 -0
  183. data/vendor/liburing/test/hardlink.c +1 -1
  184. data/vendor/liburing/test/helpers.c +54 -2
  185. data/vendor/liburing/test/helpers.h +4 -0
  186. data/vendor/liburing/test/io-cancel.c +3 -1
  187. data/vendor/liburing/test/io_uring_passthrough.c +39 -8
  188. data/vendor/liburing/test/io_uring_setup.c +3 -80
  189. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  190. data/vendor/liburing/test/iopoll.c +90 -4
  191. data/vendor/liburing/test/lfs-openat-write.c +7 -9
  192. data/vendor/liburing/test/lfs-openat.c +6 -8
  193. data/vendor/liburing/test/link_drain.c +31 -5
  194. data/vendor/liburing/test/madvise.c +1 -1
  195. data/vendor/liburing/test/msg-ring-flags.c +192 -0
  196. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  197. data/vendor/liburing/test/msg-ring.c +173 -13
  198. data/vendor/liburing/test/multicqes_drain.c +22 -19
  199. data/vendor/liburing/test/nvme.h +4 -3
  200. data/vendor/liburing/test/pipe-bug.c +95 -0
  201. data/vendor/liburing/test/poll-link.c +3 -3
  202. data/vendor/liburing/test/poll-many.c +41 -19
  203. data/vendor/liburing/test/poll-mshot-overflow.c +105 -2
  204. data/vendor/liburing/test/poll-race-mshot.c +292 -0
  205. data/vendor/liburing/test/poll-race.c +105 -0
  206. data/vendor/liburing/test/poll.c +244 -26
  207. data/vendor/liburing/test/pollfree.c +5 -5
  208. data/vendor/liburing/test/read-before-exit.c +20 -3
  209. data/vendor/liburing/test/read-write.c +2 -0
  210. data/vendor/liburing/test/recv-multishot.c +96 -3
  211. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  212. data/vendor/liburing/test/rename.c +1 -1
  213. data/vendor/liburing/test/ring-leak.c +0 -1
  214. data/vendor/liburing/test/ring-leak2.c +1 -1
  215. data/vendor/liburing/test/ringbuf-read.c +10 -6
  216. data/vendor/liburing/test/send-zerocopy.c +273 -103
  217. data/vendor/liburing/test/send_recv.c +7 -4
  218. data/vendor/liburing/test/sendmsg_fs_cve.c +2 -2
  219. data/vendor/liburing/test/single-issuer.c +7 -9
  220. data/vendor/liburing/test/skip-cqe.c +3 -4
  221. data/vendor/liburing/test/socket.c +0 -1
  222. data/vendor/liburing/test/sq-poll-dup.c +10 -3
  223. data/vendor/liburing/test/sq-poll-kthread.c +1 -1
  224. data/vendor/liburing/test/sq-poll-share.c +3 -2
  225. data/vendor/liburing/test/sqpoll-cancel-hang.c +17 -6
  226. data/vendor/liburing/test/sqpoll-disable-exit.c +4 -4
  227. data/vendor/liburing/test/symlink.c +2 -1
  228. data/vendor/liburing/test/test.h +2 -1
  229. data/vendor/liburing/test/timeout-new.c +11 -7
  230. data/vendor/liburing/test/timeout.c +1 -2
  231. data/vendor/liburing/test/unlink.c +1 -1
  232. data/vendor/liburing/test/version.c +25 -0
  233. data/vendor/liburing/test/wakeup-hang.c +1 -1
  234. data/vendor/liburing/test/xattr.c +8 -4
  235. metadata +57 -44
  236. data/docs/_config.yml +0 -64
  237. data/docs/_includes/head.html +0 -40
  238. data/docs/_includes/title.html +0 -1
  239. data/docs/_sass/custom/custom.scss +0 -10
  240. data/docs/_sass/overrides.scss +0 -0
  241. data/docs/api-reference/exception.md +0 -31
  242. data/docs/api-reference/fiber.md +0 -425
  243. data/docs/api-reference/index.md +0 -9
  244. data/docs/api-reference/io.md +0 -36
  245. data/docs/api-reference/object.md +0 -99
  246. data/docs/api-reference/polyphony-baseexception.md +0 -33
  247. data/docs/api-reference/polyphony-cancel.md +0 -26
  248. data/docs/api-reference/polyphony-moveon.md +0 -24
  249. data/docs/api-reference/polyphony-net.md +0 -20
  250. data/docs/api-reference/polyphony-process.md +0 -28
  251. data/docs/api-reference/polyphony-resourcepool.md +0 -59
  252. data/docs/api-reference/polyphony-restart.md +0 -18
  253. data/docs/api-reference/polyphony-terminate.md +0 -18
  254. data/docs/api-reference/polyphony-threadpool.md +0 -67
  255. data/docs/api-reference/polyphony-throttler.md +0 -77
  256. data/docs/api-reference/polyphony.md +0 -36
  257. data/docs/api-reference/thread.md +0 -88
  258. data/docs/favicon.ico +0 -0
  259. data/docs/getting-started/index.md +0 -10
  260. data/docs/getting-started/installing.md +0 -34
  261. data/vendor/liburing/debian/compat +0 -1
  262. data/vendor/liburing/debian/liburing1-udeb.install +0 -1
  263. data/vendor/liburing/debian/liburing1.install +0 -1
  264. data/vendor/liburing/debian/liburing1.symbols +0 -32
  265. /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
  266. /data/{docs → assets}/polyphony-logo.png +0 -0
  267. /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
@@ -48,7 +48,8 @@ static struct iovec *vecs;
48
48
  * bash -c "echo 1 > /proc/self/make-it-fail && exec ./cq-overflow.t"
49
49
  */
50
50
 
51
- static int test_io(const char *file, unsigned long usecs, unsigned *drops, int fault)
51
+ static int test_io(const char *file, unsigned long usecs, unsigned *drops,
52
+ int fault)
52
53
  {
53
54
  struct io_uring_sqe *sqe;
54
55
  struct io_uring_cqe *cqe;
@@ -60,8 +61,10 @@ static int test_io(const char *file, unsigned long usecs, unsigned *drops, int f
60
61
 
61
62
  fd = open(file, O_RDONLY | O_DIRECT);
62
63
  if (fd < 0) {
64
+ if (errno == EINVAL)
65
+ return T_EXIT_SKIP;
63
66
  perror("file open");
64
- return 1;
67
+ return T_EXIT_FAIL;
65
68
  }
66
69
 
67
70
  memset(&p, 0, sizeof(p));
@@ -69,7 +72,7 @@ static int test_io(const char *file, unsigned long usecs, unsigned *drops, int f
69
72
  if (ret) {
70
73
  close(fd);
71
74
  fprintf(stderr, "ring create failed: %d\n", ret);
72
- return 1;
75
+ return T_EXIT_FAIL;
73
76
  }
74
77
  nodrop = 0;
75
78
  if (p.features & IORING_FEAT_NODROP)
@@ -173,12 +176,12 @@ reap_it:
173
176
 
174
177
  io_uring_queue_exit(&ring);
175
178
  close(fd);
176
- return 0;
179
+ return T_EXIT_PASS;
177
180
  err:
178
181
  if (fd != -1)
179
182
  close(fd);
180
183
  io_uring_queue_exit(&ring);
181
- return 1;
184
+ return T_EXIT_SKIP;
182
185
  }
183
186
 
184
187
  static int reap_events(struct io_uring *ring, unsigned nr_events, int do_wait)
@@ -496,7 +499,10 @@ int main(int argc, char *argv[])
496
499
  do {
497
500
  drops = 0;
498
501
 
499
- if (test_io(fname, usecs, &drops, 0)) {
502
+ ret = test_io(fname, usecs, &drops, 0);
503
+ if (ret == T_EXIT_SKIP)
504
+ break;
505
+ else if (ret != T_EXIT_PASS) {
500
506
  fprintf(stderr, "test_io nofault failed\n");
501
507
  goto err;
502
508
  }
@@ -506,12 +512,12 @@ int main(int argc, char *argv[])
506
512
  iters++;
507
513
  } while (iters < 40);
508
514
 
509
- if (test_io(fname, usecs, &drops, 0)) {
515
+ if (test_io(fname, usecs, &drops, 0) == T_EXIT_FAIL) {
510
516
  fprintf(stderr, "test_io nofault failed\n");
511
517
  goto err;
512
518
  }
513
519
 
514
- if (test_io(fname, usecs, &drops, 1)) {
520
+ if (test_io(fname, usecs, &drops, 1) == T_EXIT_FAIL) {
515
521
  fprintf(stderr, "test_io fault failed\n");
516
522
  goto err;
517
523
  }
@@ -29,7 +29,7 @@ int main(int argc, char *argv[])
29
29
 
30
30
  memset(&p, 0, sizeof(p));
31
31
  p.flags = IORING_SETUP_SQPOLL;
32
- ret = t_create_ring_params(4, &ring, &p);
32
+ ret = t_create_ring_params(16, &ring, &p);
33
33
  if (ret == T_SETUP_SKIP)
34
34
  return T_EXIT_SKIP;
35
35
  else if (ret < 0)
@@ -4,7 +4,6 @@
4
4
  #include <unistd.h>
5
5
  #include <stdlib.h>
6
6
  #include <string.h>
7
- #include <error.h>
8
7
  #include <sys/eventfd.h>
9
8
  #include <signal.h>
10
9
  #include <poll.h>
@@ -57,9 +56,14 @@ static void eventfd_trigger(int fd)
57
56
  assert(ret == sizeof(val));
58
57
  }
59
58
 
60
- #define CHECK(x) if (!(x)) { \
61
- fprintf(stderr, "%s:%d %s failed\n", __FILE__, __LINE__, #x); \
62
- return -1; }
59
+ #define CHECK(x) \
60
+ do { \
61
+ if (!(x)) { \
62
+ fprintf(stderr, "%s:%d %s failed\n", __FILE__, __LINE__, #x); \
63
+ return -1; \
64
+ } \
65
+ } while (0)
66
+
63
67
 
64
68
  static int test_eventfd(void)
65
69
  {
@@ -119,7 +123,7 @@ struct thread_data {
119
123
  char buff[8];
120
124
  };
121
125
 
122
- void *thread(void *t)
126
+ static void *thread(void *t)
123
127
  {
124
128
  struct thread_data *td = t;
125
129
 
@@ -178,11 +182,11 @@ static int test_exec(const char *filename)
178
182
  int wstatus;
179
183
 
180
184
  CHECK(waitpid(fork_pid, &wstatus, 0) != (pid_t)-1);
181
- if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != T_EXIT_SKIP) {
185
+ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) == T_EXIT_FAIL) {
182
186
  fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus));
183
187
  return -1;
184
188
  }
185
- return 0;
189
+ return T_EXIT_PASS;
186
190
  }
187
191
 
188
192
  ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER |
@@ -192,9 +196,15 @@ static int test_exec(const char *filename)
192
196
 
193
197
  if (filename) {
194
198
  fd = open(filename, O_RDONLY | O_DIRECT);
199
+ if (fd < 0 && errno == EINVAL)
200
+ return T_EXIT_SKIP;
195
201
  } else {
196
202
  t_create_file(EXEC_FILENAME, EXEC_FILESIZE);
197
203
  fd = open(EXEC_FILENAME, O_RDONLY | O_DIRECT);
204
+ if (fd < 0 && errno == EINVAL) {
205
+ unlink(EXEC_FILENAME);
206
+ return T_EXIT_SKIP;
207
+ }
198
208
  unlink(EXEC_FILENAME);
199
209
  }
200
210
  buff = (char*)malloc(EXEC_FILESIZE);
@@ -207,7 +217,7 @@ static int test_exec(const char *filename)
207
217
  ret = execve("/proc/self/exe", new_argv, new_env);
208
218
  /* if we get here it failed anyway */
209
219
  fprintf(stderr, "execve failed %d\n", ret);
210
- return -1;
220
+ return T_EXIT_FAIL;
211
221
  }
212
222
 
213
223
  static int test_flag(void)
@@ -283,6 +293,45 @@ static int test_ring_shutdown(void)
283
293
  return 0;
284
294
  }
285
295
 
296
+ static int test_drain(void)
297
+ {
298
+ struct io_uring ring;
299
+ int ret, i, fd[2];
300
+ struct io_uring_sqe *sqe;
301
+ struct io_uring_cqe *cqe;
302
+ struct iovec iovecs[128];
303
+ char buff[ARRAY_SIZE(iovecs)];
304
+
305
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER |
306
+ IORING_SETUP_DEFER_TASKRUN |
307
+ IORING_SETUP_TASKRUN_FLAG);
308
+ CHECK(!ret);
309
+
310
+ for (i = 0; i < ARRAY_SIZE(iovecs); i++) {
311
+ iovecs[i].iov_base = &buff[i];
312
+ iovecs[i].iov_len = 1;
313
+ }
314
+
315
+ ret = t_create_socket_pair(fd, true);
316
+ CHECK(!ret);
317
+
318
+ sqe = io_uring_get_sqe(&ring);
319
+ io_uring_prep_writev(sqe, fd[1], &iovecs[0], ARRAY_SIZE(iovecs), 0);
320
+ sqe->flags |= IOSQE_IO_DRAIN;
321
+ io_uring_submit(&ring);
322
+
323
+ for (i = 0; i < ARRAY_SIZE(iovecs); i++)
324
+ iovecs[i].iov_base = NULL;
325
+
326
+ CHECK(io_uring_wait_cqe(&ring, &cqe) == 0);
327
+ CHECK(cqe->res == 128);
328
+
329
+ close(fd[0]);
330
+ close(fd[1]);
331
+ io_uring_queue_exit(&ring);
332
+ return 0;
333
+ }
334
+
286
335
  int main(int argc, char *argv[])
287
336
  {
288
337
  int ret;
@@ -309,7 +358,7 @@ int main(int argc, char *argv[])
309
358
  }
310
359
 
311
360
  ret = test_exec(filename);
312
- if (ret) {
361
+ if (ret == T_EXIT_FAIL) {
313
362
  fprintf(stderr, "test_exec failed\n");
314
363
  return T_EXIT_FAIL;
315
364
  }
@@ -332,5 +381,11 @@ int main(int argc, char *argv[])
332
381
  return T_EXIT_FAIL;
333
382
  }
334
383
 
384
+ ret = test_drain();
385
+ if (ret) {
386
+ fprintf(stderr, "test_drain failed\n");
387
+ return T_EXIT_FAIL;
388
+ }
389
+
335
390
  return T_EXIT_PASS;
336
391
  }
@@ -57,7 +57,7 @@ static int init_context(struct test_context *ctx, struct io_uring *ring, int nr,
57
57
  case OP_REMOVE_BUFFERS:
58
58
  io_uring_prep_remove_buffers(sqe, 10, 1);
59
59
  break;
60
- };
60
+ }
61
61
  sqe->user_data = i;
62
62
  ctx->sqes[i] = sqe;
63
63
  }
@@ -109,7 +109,7 @@ static long syz_open_dev(volatile long a0, volatile long a1, volatile long a2)
109
109
  }
110
110
  }
111
111
 
112
- uint64_t r[4] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff};
112
+ static uint64_t r[4] = {0xffffffffffffffff, 0x0, 0x0, 0xffffffffffffffff};
113
113
 
114
114
  int main(int argc, char *argv[])
115
115
  {
@@ -121,10 +121,10 @@ int main(int argc, char *argv[])
121
121
  if (argc > 1)
122
122
  return T_EXIT_SKIP;
123
123
 
124
- mmap_ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
124
+ mmap_ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, MAP_ANON|MAP_PRIVATE, -1, 0ul);
125
125
  if (mmap_ret == MAP_FAILED)
126
126
  return T_EXIT_SKIP;
127
- mmap_ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
127
+ mmap_ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, MAP_ANON|MAP_PRIVATE, -1, 0ul);
128
128
  if (mmap_ret == MAP_FAILED)
129
129
  return T_EXIT_SKIP;
130
130
  intptr_t res = 0;
@@ -102,13 +102,18 @@ int main(int argc, char *argv[])
102
102
  goto err;
103
103
  }
104
104
 
105
+ ret = T_EXIT_PASS;
105
106
  if (cqe->res != -EAGAIN && cqe->res != 4096) {
106
- printf("cqe error: %d\n", cqe->res);
107
- goto err;
107
+ if (cqe->res == -EOPNOTSUPP) {
108
+ ret = T_EXIT_SKIP;
109
+ } else {
110
+ printf("cqe error: %d\n", cqe->res);
111
+ goto err;
112
+ }
108
113
  }
109
114
 
110
115
  close(fd);
111
- return T_EXIT_PASS;
116
+ return ret;
112
117
  err:
113
118
  close(fd);
114
119
  return T_EXIT_FAIL;
@@ -0,0 +1,74 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Test that we don't recursively generate completion events if an io_uring
4
+ * fd is added to an epoll context, and the ring itself polls for events on
5
+ * the epollfd. Older kernels will stop on overflow, newer kernels will
6
+ * detect this earlier and abort correctly.
7
+ */
8
+ #include <stdio.h>
9
+ #include <unistd.h>
10
+ #include <stdlib.h>
11
+ #include <sys/epoll.h>
12
+ #include <sys/types.h>
13
+ #include <poll.h>
14
+ #include "liburing.h"
15
+ #include "helpers.h"
16
+
17
+ int main(int argc, char *argv[])
18
+ {
19
+ struct io_uring ring;
20
+ struct io_uring_sqe *sqe;
21
+ struct io_uring_cqe *cqe;
22
+ struct epoll_event ev = { };
23
+ int epollfd, ret, i;
24
+
25
+ if (argc > 1)
26
+ return T_EXIT_SKIP;
27
+
28
+ ret = io_uring_queue_init(8, &ring, 0);
29
+ if (ret) {
30
+ fprintf(stderr, "Ring init failed: %d\n", ret);
31
+ return T_EXIT_FAIL;
32
+ }
33
+
34
+ epollfd = epoll_create1(0);
35
+ if (epollfd < 0) {
36
+ perror("epoll_create");
37
+ return T_EXIT_FAIL;
38
+ }
39
+
40
+ ev.events = EPOLLIN;
41
+ ev.data.fd = ring.ring_fd;
42
+ ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, ring.ring_fd, &ev);
43
+ if (ret < 0) {
44
+ perror("epoll_ctl");
45
+ return T_EXIT_FAIL;
46
+ }
47
+
48
+ sqe = io_uring_get_sqe(&ring);
49
+ io_uring_prep_poll_multishot(sqe, epollfd, POLLIN);
50
+ sqe->user_data = 1;
51
+ io_uring_submit(&ring);
52
+
53
+ sqe = io_uring_get_sqe(&ring);
54
+ sqe->user_data = 2;
55
+ io_uring_prep_nop(sqe);
56
+ io_uring_submit(&ring);
57
+
58
+ for (i = 0; i < 2; i++) {
59
+ ret = io_uring_wait_cqe(&ring, &cqe);
60
+ if (ret) {
61
+ fprintf(stderr, "wait_cqe ret = %d\n", ret);
62
+ break;
63
+ }
64
+ io_uring_cqe_seen(&ring, cqe);
65
+ }
66
+
67
+ ret = io_uring_peek_cqe(&ring, &cqe);
68
+ if (!ret) {
69
+ fprintf(stderr, "Generated too many events\n");
70
+ return T_EXIT_FAIL;
71
+ }
72
+
73
+ return T_EXIT_PASS;
74
+ }
@@ -1,6 +1,6 @@
1
1
  /* SPDX-License-Identifier: MIT */
2
2
  /*
3
- * Description: run various nop tests
3
+ * Description: test use of eventfds with multiple rings
4
4
  *
5
5
  */
6
6
  #include <errno.h>
@@ -1,6 +1,6 @@
1
1
  /* SPDX-License-Identifier: MIT */
2
2
  /*
3
- * Description: run various nop tests
3
+ * Description: run various eventfd tests
4
4
  *
5
5
  */
6
6
  #include <errno.h>
@@ -0,0 +1,73 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Test that we don't recursively generate completion events if an io_uring
4
+ * has an eventfd registered that triggers on completions, and we add a poll
5
+ * request with multishot on the eventfd. Older kernels will stop on overflow,
6
+ * newer kernels will detect this earlier and abort correctly.
7
+ */
8
+ #include <errno.h>
9
+ #include <stdio.h>
10
+ #include <unistd.h>
11
+ #include <stdlib.h>
12
+ #include <sys/eventfd.h>
13
+ #include <sys/types.h>
14
+ #include <poll.h>
15
+ #include <assert.h>
16
+ #include "liburing.h"
17
+ #include "helpers.h"
18
+
19
+ int main(int argc, char *argv[])
20
+ {
21
+ struct io_uring ring;
22
+ struct io_uring_sqe *sqe;
23
+ struct io_uring_cqe *cqe;
24
+ int ret, efd, i;
25
+
26
+ if (argc > 1)
27
+ return T_EXIT_SKIP;
28
+
29
+ ret = io_uring_queue_init(8, &ring, 0);
30
+ if (ret) {
31
+ fprintf(stderr, "Ring init failed: %d\n", ret);
32
+ return T_EXIT_FAIL;
33
+ }
34
+
35
+ efd = eventfd(0, 0);
36
+ if (efd < 0) {
37
+ perror("eventfd");
38
+ return T_EXIT_FAIL;
39
+ }
40
+
41
+ ret = io_uring_register_eventfd(&ring, efd);
42
+ if (ret) {
43
+ fprintf(stderr, "Ring eventfd register failed: %d\n", ret);
44
+ return T_EXIT_FAIL;
45
+ }
46
+
47
+ sqe = io_uring_get_sqe(&ring);
48
+ io_uring_prep_poll_multishot(sqe, efd, POLLIN);
49
+ sqe->user_data = 1;
50
+ io_uring_submit(&ring);
51
+
52
+ sqe = io_uring_get_sqe(&ring);
53
+ sqe->user_data = 2;
54
+ io_uring_prep_nop(sqe);
55
+ io_uring_submit(&ring);
56
+
57
+ for (i = 0; i < 2; i++) {
58
+ ret = io_uring_wait_cqe(&ring, &cqe);
59
+ if (ret) {
60
+ fprintf(stderr, "wait_cqe ret = %d\n", ret);
61
+ break;
62
+ }
63
+ io_uring_cqe_seen(&ring, cqe);
64
+ }
65
+
66
+ ret = io_uring_peek_cqe(&ring, &cqe);
67
+ if (!ret) {
68
+ fprintf(stderr, "Generated too many events\n");
69
+ return T_EXIT_FAIL;
70
+ }
71
+
72
+ return T_EXIT_PASS;
73
+ }
@@ -26,7 +26,7 @@ static pthread_barrier_t init_barrier;
26
26
  static int sleep_fd, notify_fd;
27
27
  static sem_t sem;
28
28
 
29
- void *thread_func(void *arg)
29
+ static void *thread_func(void *arg)
30
30
  {
31
31
  struct io_uring ring;
32
32
  int res;
@@ -186,7 +186,7 @@ int main(int argc, char *argv[])
186
186
  }
187
187
 
188
188
  /* too hard to reliably test, just ignore */
189
- if (0 && bad > good) {
189
+ if ((0) && bad > good) {
190
190
  fprintf(stderr, "Suspicious timings\n");
191
191
  goto err;
192
192
  }
@@ -54,7 +54,7 @@ static int inject_fault(int nth)
54
54
  return fd;
55
55
  }
56
56
 
57
- static int setup_fault()
57
+ static int setup_fault(void)
58
58
  {
59
59
  static struct {
60
60
  const char* file;
@@ -79,13 +79,13 @@ static int setup_fault()
79
79
  return 0;
80
80
  }
81
81
 
82
- uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
82
+ static uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
83
83
 
84
84
  int main(int argc, char *argv[])
85
85
  {
86
86
  if (argc > 1)
87
87
  return T_EXIT_SKIP;
88
- mmap((void *) 0x20000000ul, 0x1000000ul, 3ul, 0x32ul, -1, 0);
88
+ mmap((void *) 0x20000000ul, 0x1000000ul, 3ul, MAP_ANON|MAP_PRIVATE, -1, 0);
89
89
  if (setup_fault()) {
90
90
  printf("Test needs failslab/fail_futex/fail_page_alloc enabled, skipped\n");
91
91
  return T_EXIT_SKIP;
@@ -13,8 +13,9 @@
13
13
  #include "liburing.h"
14
14
  #include "helpers.h"
15
15
 
16
- #define FSIZE 128
17
- #define PAT 0x9a
16
+ #define FSIZE 128
17
+ #define PAT 0x9a
18
+ #define USER_DATA 0x89
18
19
 
19
20
  static int no_fd_pass;
20
21
 
@@ -49,7 +50,7 @@ static int verify_fixed_read(struct io_uring *ring, int fixed_fd, int fail)
49
50
  return 0;
50
51
  }
51
52
 
52
- static int test(const char *filename)
53
+ static int test(const char *filename, int source_fd, int target_fd)
53
54
  {
54
55
  struct io_uring sring, dring;
55
56
  struct io_uring_sqe *sqe;
@@ -82,7 +83,7 @@ static int test(const char *filename)
82
83
 
83
84
  /* open direct descriptor */
84
85
  sqe = io_uring_get_sqe(&sring);
85
- io_uring_prep_openat_direct(sqe, AT_FDCWD, filename, 0, 0644, 0);
86
+ io_uring_prep_openat_direct(sqe, AT_FDCWD, filename, 0, 0644, source_fd);
86
87
  io_uring_submit(&sring);
87
88
  ret = io_uring_wait_cqe(&sring, &cqe);
88
89
  if (ret) {
@@ -96,15 +97,13 @@ static int test(const char *filename)
96
97
  io_uring_cqe_seen(&sring, cqe);
97
98
 
98
99
  /* verify data is sane for source ring */
99
- if (verify_fixed_read(&sring, 0, 0))
100
+ if (verify_fixed_read(&sring, source_fd, 0))
100
101
  return T_EXIT_FAIL;
101
102
 
102
103
  /* send direct descriptor to destination ring */
103
104
  sqe = io_uring_get_sqe(&sring);
104
- io_uring_prep_msg_ring(sqe, dring.ring_fd, 0, 0x89, 0);
105
- sqe->addr = 1;
106
- sqe->addr3 = 0;
107
- sqe->file_index = 1;
105
+ io_uring_prep_msg_ring_fd(sqe, dring.ring_fd, source_fd, target_fd,
106
+ USER_DATA, 0);
108
107
  io_uring_submit(&sring);
109
108
 
110
109
  ret = io_uring_wait_cqe(&sring, &cqe);
@@ -128,19 +127,19 @@ static int test(const char *filename)
128
127
  fprintf(stderr, "wait cqe failed %d\n", ret);
129
128
  return T_EXIT_FAIL;
130
129
  }
131
- if (cqe->user_data != 0x89) {
130
+ if (cqe->user_data != USER_DATA) {
132
131
  fprintf(stderr, "bad user_data %ld\n", (long) cqe->res);
133
132
  return T_EXIT_FAIL;
134
133
  }
135
134
  io_uring_cqe_seen(&dring, cqe);
136
135
 
137
136
  /* now verify we can read the sane data from the destination ring */
138
- if (verify_fixed_read(&dring, 0, 0))
137
+ if (verify_fixed_read(&dring, target_fd, 0))
139
138
  return T_EXIT_FAIL;
140
139
 
141
140
  /* close descriptor in source ring */
142
141
  sqe = io_uring_get_sqe(&sring);
143
- io_uring_prep_close_direct(sqe, 0);
142
+ io_uring_prep_close_direct(sqe, source_fd);
144
143
  io_uring_submit(&sring);
145
144
 
146
145
  ret = io_uring_wait_cqe(&sring, &cqe);
@@ -155,13 +154,15 @@ static int test(const char *filename)
155
154
  io_uring_cqe_seen(&sring, cqe);
156
155
 
157
156
  /* check that source ring fails after close */
158
- if (verify_fixed_read(&sring, 0, 1))
157
+ if (verify_fixed_read(&sring, source_fd, 1))
159
158
  return T_EXIT_FAIL;
160
159
 
161
160
  /* check we can still read from destination ring */
162
- if (verify_fixed_read(&dring, 0, 0))
161
+ if (verify_fixed_read(&dring, target_fd, 0))
163
162
  return T_EXIT_FAIL;
164
163
 
164
+ io_uring_queue_exit(&sring);
165
+ io_uring_queue_exit(&dring);
165
166
  return T_EXIT_PASS;
166
167
  }
167
168
 
@@ -176,9 +177,27 @@ int main(int argc, char *argv[])
176
177
  sprintf(fname, ".fd-pass.%d", getpid());
177
178
  t_create_file_pattern(fname, FSIZE, PAT);
178
179
 
179
- ret = test(fname);
180
+ ret = test(fname, 0, 1);
180
181
  if (ret == T_EXIT_FAIL) {
181
- fprintf(stderr, "test failed\n");
182
+ fprintf(stderr, "test failed 0 1\n");
183
+ ret = T_EXIT_FAIL;
184
+ }
185
+
186
+ ret = test(fname, 0, 2);
187
+ if (ret == T_EXIT_FAIL) {
188
+ fprintf(stderr, "test failed 0 2\n");
189
+ ret = T_EXIT_FAIL;
190
+ }
191
+
192
+ ret = test(fname, 1, 1);
193
+ if (ret == T_EXIT_FAIL) {
194
+ fprintf(stderr, "test failed 1 1\n");
195
+ ret = T_EXIT_FAIL;
196
+ }
197
+
198
+ ret = test(fname, 1, 0);
199
+ if (ret == T_EXIT_FAIL) {
200
+ fprintf(stderr, "test failed 1 0\n");
182
201
  ret = T_EXIT_FAIL;
183
202
  }
184
203
 
@@ -935,6 +935,59 @@ static int test_zero_range_alloc(struct io_uring *ring, int fds[2])
935
935
  return 0;
936
936
  }
937
937
 
938
+ static int test_defer_taskrun(void)
939
+ {
940
+ struct io_uring_sqe *sqe;
941
+ struct io_uring ring;
942
+ int ret, fds[2];
943
+ char buff = 'x';
944
+
945
+ ret = io_uring_queue_init(8, &ring,
946
+ IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER);
947
+ if (ret) {
948
+ fprintf(stderr, "ring init\n");
949
+ return 1;
950
+ }
951
+
952
+ ret = pipe(fds);
953
+ if (ret) {
954
+ fprintf(stderr, "bad pipes\n");
955
+ return 1;
956
+ }
957
+
958
+ ret = io_uring_register_files(&ring, &fds[0], 2);
959
+ if (ret) {
960
+ fprintf(stderr, "bad register %d\n", ret);
961
+ return 1;
962
+ }
963
+
964
+ sqe = io_uring_get_sqe(&ring);
965
+ io_uring_prep_read(sqe, 0, &buff, 1, 0);
966
+ sqe->flags |= IOSQE_FIXED_FILE;
967
+ ret = io_uring_submit(&ring);
968
+ if (ret != 1) {
969
+ fprintf(stderr, "bad submit\n");
970
+ return 1;
971
+ }
972
+
973
+ ret = write(fds[1], &buff, 1);
974
+ if (ret != 1) {
975
+ fprintf(stderr, "bad pipe write\n");
976
+ return 1;
977
+ }
978
+
979
+ ret = io_uring_unregister_files(&ring);
980
+ if (ret) {
981
+ fprintf(stderr, "bad unregister %d\n", ret);
982
+ return 1;
983
+ }
984
+
985
+ close(fds[0]);
986
+ close(fds[1]);
987
+ io_uring_queue_exit(&ring);
988
+ return 0;
989
+ }
990
+
938
991
  static int test_file_alloc_ranges(void)
939
992
  {
940
993
  struct io_uring ring;
@@ -1120,5 +1173,13 @@ int main(int argc, char *argv[])
1120
1173
  return T_EXIT_FAIL;
1121
1174
  }
1122
1175
 
1176
+ if (t_probe_defer_taskrun()) {
1177
+ ret = test_defer_taskrun();
1178
+ if (ret) {
1179
+ fprintf(stderr, "test_defer_taskrun failed\n");
1180
+ return T_EXIT_FAIL;
1181
+ }
1182
+ }
1183
+
1123
1184
  return T_EXIT_PASS;
1124
1185
  }
@@ -10,7 +10,6 @@
10
10
  #include <string.h>
11
11
  #include <fcntl.h>
12
12
  #include <assert.h>
13
- #include <string.h>
14
13
  #include <sys/ioctl.h>
15
14
  #include <sys/stat.h>
16
15
  #include <linux/fs.h>
@@ -46,7 +45,8 @@ static int verify_buf(void *buf, size_t size, off_t off)
46
45
  ptr = buf;
47
46
  for (i = 0; i < u_in_buf; i++) {
48
47
  if (off != *ptr) {
49
- fprintf(stderr, "Found %u, wanted %lu\n", *ptr, off);
48
+ fprintf(stderr, "Found %u, wanted %llu\n", *ptr,
49
+ (unsigned long long) off);
50
50
  return 1;
51
51
  }
52
52
  ptr++;