thread-exit.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: test that thread pool issued requests don't cancel on thread
  5. * exit, but do get canceled once the parent exits. Do both
  6. * writes that finish and a poll request that sticks around.
  7. *
  8. */
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include <unistd.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <fcntl.h>
  15. #include <poll.h>
  16. #include <pthread.h>
  17. #include "helpers.h"
  18. #include "liburing.h"
  19. #define NR_IOS 8
  20. #define WSIZE 512
  21. struct d {
  22. int fd;
  23. struct io_uring *ring;
  24. unsigned long off;
  25. int pipe_fd;
  26. int err;
  27. int i;
  28. };
  29. static char *g_buf[NR_IOS] = {NULL};
  30. static void free_g_buf(void)
  31. {
  32. int i;
  33. for (i = 0; i < NR_IOS; i++)
  34. free(g_buf[i]);
  35. }
  36. static void *do_io(void *data)
  37. {
  38. struct d *d = data;
  39. struct io_uring_sqe *sqe;
  40. char *buffer;
  41. int ret;
  42. buffer = t_malloc(WSIZE);
  43. g_buf[d->i] = buffer;
  44. memset(buffer, 0x5a, WSIZE);
  45. sqe = io_uring_get_sqe(d->ring);
  46. if (!sqe) {
  47. d->err++;
  48. return NULL;
  49. }
  50. io_uring_prep_write(sqe, d->fd, buffer, WSIZE, d->off);
  51. sqe->user_data = d->off;
  52. sqe = io_uring_get_sqe(d->ring);
  53. if (!sqe) {
  54. d->err++;
  55. return NULL;
  56. }
  57. io_uring_prep_poll_add(sqe, d->pipe_fd, POLLIN);
  58. ret = io_uring_submit(d->ring);
  59. if (ret != 2)
  60. d->err++;
  61. return NULL;
  62. }
  63. int main(int argc, char *argv[])
  64. {
  65. struct io_uring ring;
  66. const char *fname;
  67. pthread_t thread;
  68. int ret, do_unlink, i, fd;
  69. struct d d;
  70. int fds[2];
  71. if (pipe(fds) < 0) {
  72. perror("pipe");
  73. return 1;
  74. }
  75. ret = io_uring_queue_init(32, &ring, 0);
  76. if (ret) {
  77. fprintf(stderr, "ring setup failed\n");
  78. return 1;
  79. }
  80. if (argc > 1) {
  81. fname = argv[1];
  82. do_unlink = 0;
  83. } else {
  84. fname = ".thread.exit";
  85. do_unlink = 1;
  86. t_create_file(fname, 4096);
  87. }
  88. fd = open(fname, O_WRONLY);
  89. if (do_unlink)
  90. unlink(fname);
  91. if (fd < 0) {
  92. perror("open");
  93. return 1;
  94. }
  95. d.fd = fd;
  96. d.ring = &ring;
  97. d.off = 0;
  98. d.pipe_fd = fds[0];
  99. d.err = 0;
  100. for (i = 0; i < NR_IOS; i++) {
  101. d.i = i;
  102. memset(&thread, 0, sizeof(thread));
  103. pthread_create(&thread, NULL, do_io, &d);
  104. pthread_join(thread, NULL);
  105. d.off += WSIZE;
  106. }
  107. for (i = 0; i < NR_IOS; i++) {
  108. struct io_uring_cqe *cqe;
  109. ret = io_uring_wait_cqe(&ring, &cqe);
  110. if (ret) {
  111. fprintf(stderr, "io_uring_wait_cqe=%d\n", ret);
  112. goto err;
  113. }
  114. if (cqe->res != WSIZE) {
  115. fprintf(stderr, "cqe->res=%d, Expected %d\n", cqe->res,
  116. WSIZE);
  117. goto err;
  118. }
  119. io_uring_cqe_seen(&ring, cqe);
  120. }
  121. free_g_buf();
  122. return d.err;
  123. err:
  124. free_g_buf();
  125. return 1;
  126. }