1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci#include "uv.h"
23e66f31c5Sopenharmony_ci#include "task.h"
24e66f31c5Sopenharmony_ci
25e66f31c5Sopenharmony_ci#ifdef _WIN32
26e66f31c5Sopenharmony_ci# define putenv _putenv
27e66f31c5Sopenharmony_ci#endif
28e66f31c5Sopenharmony_ci
29e66f31c5Sopenharmony_ci#define INIT_CANCEL_INFO(ci, what)                                            \
30e66f31c5Sopenharmony_ci  do {                                                                        \
31e66f31c5Sopenharmony_ci    (ci)->reqs = (what);                                                      \
32e66f31c5Sopenharmony_ci    (ci)->nreqs = ARRAY_SIZE(what);                                           \
33e66f31c5Sopenharmony_ci    (ci)->stride = sizeof((what)[0]);                                         \
34e66f31c5Sopenharmony_ci  }                                                                           \
35e66f31c5Sopenharmony_ci  while (0)
36e66f31c5Sopenharmony_ci
37e66f31c5Sopenharmony_cistruct cancel_info {
38e66f31c5Sopenharmony_ci  void* reqs;
39e66f31c5Sopenharmony_ci  unsigned nreqs;
40e66f31c5Sopenharmony_ci  unsigned stride;
41e66f31c5Sopenharmony_ci  uv_timer_t timer_handle;
42e66f31c5Sopenharmony_ci};
43e66f31c5Sopenharmony_ci
44e66f31c5Sopenharmony_cistruct random_info {
45e66f31c5Sopenharmony_ci  uv_random_t random_req;
46e66f31c5Sopenharmony_ci  char buf[1];
47e66f31c5Sopenharmony_ci};
48e66f31c5Sopenharmony_ci
49e66f31c5Sopenharmony_cistatic unsigned fs_cb_called;
50e66f31c5Sopenharmony_cistatic unsigned done_cb_called;
51e66f31c5Sopenharmony_cistatic unsigned done2_cb_called;
52e66f31c5Sopenharmony_cistatic unsigned timer_cb_called;
53e66f31c5Sopenharmony_cistatic uv_work_t pause_reqs[4];
54e66f31c5Sopenharmony_cistatic uv_sem_t pause_sems[ARRAY_SIZE(pause_reqs)];
55e66f31c5Sopenharmony_ci
56e66f31c5Sopenharmony_ci
57e66f31c5Sopenharmony_cistatic void work_cb(uv_work_t* req) {
58e66f31c5Sopenharmony_ci  uv_sem_wait(pause_sems + (req - pause_reqs));
59e66f31c5Sopenharmony_ci}
60e66f31c5Sopenharmony_ci
61e66f31c5Sopenharmony_ci
62e66f31c5Sopenharmony_cistatic void done_cb(uv_work_t* req, int status) {
63e66f31c5Sopenharmony_ci  uv_sem_destroy(pause_sems + (req - pause_reqs));
64e66f31c5Sopenharmony_ci}
65e66f31c5Sopenharmony_ci
66e66f31c5Sopenharmony_ci
67e66f31c5Sopenharmony_cistatic void saturate_threadpool(void) {
68e66f31c5Sopenharmony_ci  uv_loop_t* loop;
69e66f31c5Sopenharmony_ci  char buf[64];
70e66f31c5Sopenharmony_ci  size_t i;
71e66f31c5Sopenharmony_ci
72e66f31c5Sopenharmony_ci  snprintf(buf,
73e66f31c5Sopenharmony_ci           sizeof(buf),
74e66f31c5Sopenharmony_ci           "UV_THREADPOOL_SIZE=%lu",
75e66f31c5Sopenharmony_ci           (unsigned long)ARRAY_SIZE(pause_reqs));
76e66f31c5Sopenharmony_ci  putenv(buf);
77e66f31c5Sopenharmony_ci
78e66f31c5Sopenharmony_ci  loop = uv_default_loop();
79e66f31c5Sopenharmony_ci  for (i = 0; i < ARRAY_SIZE(pause_reqs); i += 1) {
80e66f31c5Sopenharmony_ci    ASSERT_OK(uv_sem_init(pause_sems + i, 0));
81e66f31c5Sopenharmony_ci    ASSERT_OK(uv_queue_work(loop, pause_reqs + i, work_cb, done_cb));
82e66f31c5Sopenharmony_ci  }
83e66f31c5Sopenharmony_ci}
84e66f31c5Sopenharmony_ci
85e66f31c5Sopenharmony_ci
86e66f31c5Sopenharmony_cistatic void unblock_threadpool(void) {
87e66f31c5Sopenharmony_ci  size_t i;
88e66f31c5Sopenharmony_ci
89e66f31c5Sopenharmony_ci  for (i = 0; i < ARRAY_SIZE(pause_reqs); i += 1)
90e66f31c5Sopenharmony_ci    uv_sem_post(pause_sems + i);
91e66f31c5Sopenharmony_ci}
92e66f31c5Sopenharmony_ci
93e66f31c5Sopenharmony_ci
94e66f31c5Sopenharmony_cistatic int known_broken(uv_req_t* req) {
95e66f31c5Sopenharmony_ci  if (req->type != UV_FS)
96e66f31c5Sopenharmony_ci    return 0;
97e66f31c5Sopenharmony_ci
98e66f31c5Sopenharmony_ci#ifdef __linux__
99e66f31c5Sopenharmony_ci  /* TODO(bnoordhuis) make cancellation work with io_uring */
100e66f31c5Sopenharmony_ci  switch (((uv_fs_t*) req)->fs_type) {
101e66f31c5Sopenharmony_ci    case UV_FS_CLOSE:
102e66f31c5Sopenharmony_ci    case UV_FS_FDATASYNC:
103e66f31c5Sopenharmony_ci    case UV_FS_FSTAT:
104e66f31c5Sopenharmony_ci    case UV_FS_FSYNC:
105e66f31c5Sopenharmony_ci    case UV_FS_LINK:
106e66f31c5Sopenharmony_ci    case UV_FS_LSTAT:
107e66f31c5Sopenharmony_ci    case UV_FS_MKDIR:
108e66f31c5Sopenharmony_ci    case UV_FS_OPEN:
109e66f31c5Sopenharmony_ci    case UV_FS_READ:
110e66f31c5Sopenharmony_ci    case UV_FS_RENAME:
111e66f31c5Sopenharmony_ci    case UV_FS_STAT:
112e66f31c5Sopenharmony_ci    case UV_FS_SYMLINK:
113e66f31c5Sopenharmony_ci    case UV_FS_WRITE:
114e66f31c5Sopenharmony_ci    case UV_FS_UNLINK:
115e66f31c5Sopenharmony_ci      return 1;
116e66f31c5Sopenharmony_ci    default:  /* Squelch -Wswitch warnings. */
117e66f31c5Sopenharmony_ci      break;
118e66f31c5Sopenharmony_ci  }
119e66f31c5Sopenharmony_ci#endif
120e66f31c5Sopenharmony_ci
121e66f31c5Sopenharmony_ci  return 0;
122e66f31c5Sopenharmony_ci}
123e66f31c5Sopenharmony_ci
124e66f31c5Sopenharmony_ci
125e66f31c5Sopenharmony_cistatic void fs_cb(uv_fs_t* req) {
126e66f31c5Sopenharmony_ci  ASSERT_NE(known_broken((uv_req_t*) req) || \
127e66f31c5Sopenharmony_ci      req->result == UV_ECANCELED, 0);
128e66f31c5Sopenharmony_ci  uv_fs_req_cleanup(req);
129e66f31c5Sopenharmony_ci  fs_cb_called++;
130e66f31c5Sopenharmony_ci}
131e66f31c5Sopenharmony_ci
132e66f31c5Sopenharmony_ci
133e66f31c5Sopenharmony_cistatic void getaddrinfo_cb(uv_getaddrinfo_t* req,
134e66f31c5Sopenharmony_ci                           int status,
135e66f31c5Sopenharmony_ci                           struct addrinfo* res) {
136e66f31c5Sopenharmony_ci  ASSERT_EQ(status, UV_EAI_CANCELED);
137e66f31c5Sopenharmony_ci  ASSERT_NULL(res);
138e66f31c5Sopenharmony_ci  uv_freeaddrinfo(res);  /* Should not crash. */
139e66f31c5Sopenharmony_ci}
140e66f31c5Sopenharmony_ci
141e66f31c5Sopenharmony_ci
142e66f31c5Sopenharmony_cistatic void getnameinfo_cb(uv_getnameinfo_t* handle,
143e66f31c5Sopenharmony_ci                           int status,
144e66f31c5Sopenharmony_ci                           const char* hostname,
145e66f31c5Sopenharmony_ci                           const char* service) {
146e66f31c5Sopenharmony_ci  ASSERT_EQ(status, UV_EAI_CANCELED);
147e66f31c5Sopenharmony_ci  ASSERT_NULL(hostname);
148e66f31c5Sopenharmony_ci  ASSERT_NULL(service);
149e66f31c5Sopenharmony_ci}
150e66f31c5Sopenharmony_ci
151e66f31c5Sopenharmony_ci
152e66f31c5Sopenharmony_cistatic void work2_cb(uv_work_t* req) {
153e66f31c5Sopenharmony_ci  ASSERT(0 && "work2_cb called");
154e66f31c5Sopenharmony_ci}
155e66f31c5Sopenharmony_ci
156e66f31c5Sopenharmony_ci
157e66f31c5Sopenharmony_cistatic void done2_cb(uv_work_t* req, int status) {
158e66f31c5Sopenharmony_ci  ASSERT_EQ(status, UV_ECANCELED);
159e66f31c5Sopenharmony_ci  done2_cb_called++;
160e66f31c5Sopenharmony_ci}
161e66f31c5Sopenharmony_ci
162e66f31c5Sopenharmony_ci
163e66f31c5Sopenharmony_cistatic void timer_cb(uv_timer_t* handle) {
164e66f31c5Sopenharmony_ci  struct cancel_info* ci;
165e66f31c5Sopenharmony_ci  uv_req_t* req;
166e66f31c5Sopenharmony_ci  unsigned i;
167e66f31c5Sopenharmony_ci
168e66f31c5Sopenharmony_ci  ci = container_of(handle, struct cancel_info, timer_handle);
169e66f31c5Sopenharmony_ci
170e66f31c5Sopenharmony_ci  for (i = 0; i < ci->nreqs; i++) {
171e66f31c5Sopenharmony_ci    req = (uv_req_t*) ((char*) ci->reqs + i * ci->stride);
172e66f31c5Sopenharmony_ci    ASSERT(known_broken(req) || 0 == uv_cancel(req));
173e66f31c5Sopenharmony_ci  }
174e66f31c5Sopenharmony_ci
175e66f31c5Sopenharmony_ci  uv_close((uv_handle_t*) &ci->timer_handle, NULL);
176e66f31c5Sopenharmony_ci  unblock_threadpool();
177e66f31c5Sopenharmony_ci  timer_cb_called++;
178e66f31c5Sopenharmony_ci}
179e66f31c5Sopenharmony_ci
180e66f31c5Sopenharmony_ci
181e66f31c5Sopenharmony_cistatic void nop_done_cb(uv_work_t* req, int status) {
182e66f31c5Sopenharmony_ci  ASSERT_EQ(status, UV_ECANCELED);
183e66f31c5Sopenharmony_ci  done_cb_called++;
184e66f31c5Sopenharmony_ci}
185e66f31c5Sopenharmony_ci
186e66f31c5Sopenharmony_ci
187e66f31c5Sopenharmony_cistatic void nop_random_cb(uv_random_t* req, int status, void* buf, size_t len) {
188e66f31c5Sopenharmony_ci  struct random_info* ri;
189e66f31c5Sopenharmony_ci
190e66f31c5Sopenharmony_ci  ri = container_of(req, struct random_info, random_req);
191e66f31c5Sopenharmony_ci
192e66f31c5Sopenharmony_ci  ASSERT_EQ(status, UV_ECANCELED);
193e66f31c5Sopenharmony_ci  ASSERT_PTR_EQ(buf, (void*) ri->buf);
194e66f31c5Sopenharmony_ci  ASSERT_EQ(len, sizeof(ri->buf));
195e66f31c5Sopenharmony_ci
196e66f31c5Sopenharmony_ci  done_cb_called++;
197e66f31c5Sopenharmony_ci}
198e66f31c5Sopenharmony_ci
199e66f31c5Sopenharmony_ci
200e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_getaddrinfo) {
201e66f31c5Sopenharmony_ci  uv_getaddrinfo_t reqs[4];
202e66f31c5Sopenharmony_ci  struct cancel_info ci;
203e66f31c5Sopenharmony_ci  struct addrinfo hints;
204e66f31c5Sopenharmony_ci  uv_loop_t* loop;
205e66f31c5Sopenharmony_ci  int r;
206e66f31c5Sopenharmony_ci
207e66f31c5Sopenharmony_ci  INIT_CANCEL_INFO(&ci, reqs);
208e66f31c5Sopenharmony_ci  loop = uv_default_loop();
209e66f31c5Sopenharmony_ci  saturate_threadpool();
210e66f31c5Sopenharmony_ci
211e66f31c5Sopenharmony_ci  r = uv_getaddrinfo(loop, reqs + 0, getaddrinfo_cb, "fail", NULL, NULL);
212e66f31c5Sopenharmony_ci  ASSERT_OK(r);
213e66f31c5Sopenharmony_ci
214e66f31c5Sopenharmony_ci  r = uv_getaddrinfo(loop, reqs + 1, getaddrinfo_cb, NULL, "fail", NULL);
215e66f31c5Sopenharmony_ci  ASSERT_OK(r);
216e66f31c5Sopenharmony_ci
217e66f31c5Sopenharmony_ci  r = uv_getaddrinfo(loop, reqs + 2, getaddrinfo_cb, "fail", "fail", NULL);
218e66f31c5Sopenharmony_ci  ASSERT_OK(r);
219e66f31c5Sopenharmony_ci
220e66f31c5Sopenharmony_ci  r = uv_getaddrinfo(loop, reqs + 3, getaddrinfo_cb, "fail", NULL, &hints);
221e66f31c5Sopenharmony_ci  ASSERT_OK(r);
222e66f31c5Sopenharmony_ci
223e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_init(loop, &ci.timer_handle));
224e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_start(&ci.timer_handle, timer_cb, 10, 0));
225e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
226e66f31c5Sopenharmony_ci  ASSERT_EQ(1, timer_cb_called);
227e66f31c5Sopenharmony_ci
228e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
229e66f31c5Sopenharmony_ci  return 0;
230e66f31c5Sopenharmony_ci}
231e66f31c5Sopenharmony_ci
232e66f31c5Sopenharmony_ci
233e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_getnameinfo) {
234e66f31c5Sopenharmony_ci  uv_getnameinfo_t reqs[4];
235e66f31c5Sopenharmony_ci  struct sockaddr_in addr4;
236e66f31c5Sopenharmony_ci  struct cancel_info ci;
237e66f31c5Sopenharmony_ci  uv_loop_t* loop;
238e66f31c5Sopenharmony_ci  int r;
239e66f31c5Sopenharmony_ci
240e66f31c5Sopenharmony_ci  r = uv_ip4_addr("127.0.0.1", 80, &addr4);
241e66f31c5Sopenharmony_ci  ASSERT_OK(r);
242e66f31c5Sopenharmony_ci
243e66f31c5Sopenharmony_ci  INIT_CANCEL_INFO(&ci, reqs);
244e66f31c5Sopenharmony_ci  loop = uv_default_loop();
245e66f31c5Sopenharmony_ci  saturate_threadpool();
246e66f31c5Sopenharmony_ci
247e66f31c5Sopenharmony_ci  r = uv_getnameinfo(loop, reqs + 0, getnameinfo_cb, (const struct sockaddr*)&addr4, 0);
248e66f31c5Sopenharmony_ci  ASSERT_OK(r);
249e66f31c5Sopenharmony_ci
250e66f31c5Sopenharmony_ci  r = uv_getnameinfo(loop, reqs + 1, getnameinfo_cb, (const struct sockaddr*)&addr4, 0);
251e66f31c5Sopenharmony_ci  ASSERT_OK(r);
252e66f31c5Sopenharmony_ci
253e66f31c5Sopenharmony_ci  r = uv_getnameinfo(loop, reqs + 2, getnameinfo_cb, (const struct sockaddr*)&addr4, 0);
254e66f31c5Sopenharmony_ci  ASSERT_OK(r);
255e66f31c5Sopenharmony_ci
256e66f31c5Sopenharmony_ci  r = uv_getnameinfo(loop, reqs + 3, getnameinfo_cb, (const struct sockaddr*)&addr4, 0);
257e66f31c5Sopenharmony_ci  ASSERT_OK(r);
258e66f31c5Sopenharmony_ci
259e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_init(loop, &ci.timer_handle));
260e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_start(&ci.timer_handle, timer_cb, 10, 0));
261e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
262e66f31c5Sopenharmony_ci  ASSERT_EQ(1, timer_cb_called);
263e66f31c5Sopenharmony_ci
264e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
265e66f31c5Sopenharmony_ci  return 0;
266e66f31c5Sopenharmony_ci}
267e66f31c5Sopenharmony_ci
268e66f31c5Sopenharmony_ci
269e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_random) {
270e66f31c5Sopenharmony_ci  struct random_info req;
271e66f31c5Sopenharmony_ci  uv_loop_t* loop;
272e66f31c5Sopenharmony_ci
273e66f31c5Sopenharmony_ci  saturate_threadpool();
274e66f31c5Sopenharmony_ci  loop = uv_default_loop();
275e66f31c5Sopenharmony_ci  ASSERT_OK(uv_random(loop,
276e66f31c5Sopenharmony_ci                      &req.random_req,
277e66f31c5Sopenharmony_ci                      &req.buf,
278e66f31c5Sopenharmony_ci                      sizeof(req.buf),
279e66f31c5Sopenharmony_ci                      0,
280e66f31c5Sopenharmony_ci                      nop_random_cb));
281e66f31c5Sopenharmony_ci  ASSERT_OK(uv_cancel((uv_req_t*) &req));
282e66f31c5Sopenharmony_ci  ASSERT_OK(done_cb_called);
283e66f31c5Sopenharmony_ci  unblock_threadpool();
284e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
285e66f31c5Sopenharmony_ci  ASSERT_EQ(1, done_cb_called);
286e66f31c5Sopenharmony_ci
287e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
288e66f31c5Sopenharmony_ci  return 0;
289e66f31c5Sopenharmony_ci}
290e66f31c5Sopenharmony_ci
291e66f31c5Sopenharmony_ci
292e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_work) {
293e66f31c5Sopenharmony_ci  struct cancel_info ci;
294e66f31c5Sopenharmony_ci  uv_work_t reqs[16];
295e66f31c5Sopenharmony_ci  uv_loop_t* loop;
296e66f31c5Sopenharmony_ci  unsigned i;
297e66f31c5Sopenharmony_ci
298e66f31c5Sopenharmony_ci  INIT_CANCEL_INFO(&ci, reqs);
299e66f31c5Sopenharmony_ci  loop = uv_default_loop();
300e66f31c5Sopenharmony_ci  saturate_threadpool();
301e66f31c5Sopenharmony_ci
302e66f31c5Sopenharmony_ci  for (i = 0; i < ARRAY_SIZE(reqs); i++)
303e66f31c5Sopenharmony_ci    ASSERT_OK(uv_queue_work(loop, reqs + i, work2_cb, done2_cb));
304e66f31c5Sopenharmony_ci
305e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_init(loop, &ci.timer_handle));
306e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_start(&ci.timer_handle, timer_cb, 10, 0));
307e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
308e66f31c5Sopenharmony_ci  ASSERT_EQ(1, timer_cb_called);
309e66f31c5Sopenharmony_ci  ASSERT_EQ(ARRAY_SIZE(reqs), done2_cb_called);
310e66f31c5Sopenharmony_ci
311e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
312e66f31c5Sopenharmony_ci  return 0;
313e66f31c5Sopenharmony_ci}
314e66f31c5Sopenharmony_ci
315e66f31c5Sopenharmony_ci
316e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_fs) {
317e66f31c5Sopenharmony_ci  struct cancel_info ci;
318e66f31c5Sopenharmony_ci  uv_fs_t reqs[26];
319e66f31c5Sopenharmony_ci  uv_loop_t* loop;
320e66f31c5Sopenharmony_ci  unsigned n;
321e66f31c5Sopenharmony_ci  uv_buf_t iov;
322e66f31c5Sopenharmony_ci
323e66f31c5Sopenharmony_ci  INIT_CANCEL_INFO(&ci, reqs);
324e66f31c5Sopenharmony_ci  loop = uv_default_loop();
325e66f31c5Sopenharmony_ci  saturate_threadpool();
326e66f31c5Sopenharmony_ci  iov = uv_buf_init(NULL, 0);
327e66f31c5Sopenharmony_ci
328e66f31c5Sopenharmony_ci  /* Needs to match ARRAY_SIZE(fs_reqs). */
329e66f31c5Sopenharmony_ci  n = 0;
330e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_chmod(loop, reqs + n++, "/", 0, fs_cb));
331e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_chown(loop, reqs + n++, "/", 0, 0, fs_cb));
332e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_close(loop, reqs + n++, 0, fs_cb));
333e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_fchmod(loop, reqs + n++, 0, 0, fs_cb));
334e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_fchown(loop, reqs + n++, 0, 0, 0, fs_cb));
335e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_fdatasync(loop, reqs + n++, 0, fs_cb));
336e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_fstat(loop, reqs + n++, 0, fs_cb));
337e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_fsync(loop, reqs + n++, 0, fs_cb));
338e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_ftruncate(loop, reqs + n++, 0, 0, fs_cb));
339e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_futime(loop, reqs + n++, 0, 0, 0, fs_cb));
340e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_link(loop, reqs + n++, "/", "/", fs_cb));
341e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_lstat(loop, reqs + n++, "/", fs_cb));
342e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
343e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_open(loop, reqs + n++, "/", 0, 0, fs_cb));
344e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_read(loop, reqs + n++, -1, &iov, 1, 0, fs_cb));
345e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb));
346e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_readlink(loop, reqs + n++, "/", fs_cb));
347e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_realpath(loop, reqs + n++, "/", fs_cb));
348e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb));
349e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
350e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_sendfile(loop, reqs + n++, 0, 0, 0, 0, fs_cb));
351e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_stat(loop, reqs + n++, "/", fs_cb));
352e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_symlink(loop, reqs + n++, "/", "/", 0, fs_cb));
353e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_unlink(loop, reqs + n++, "/", fs_cb));
354e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_utime(loop, reqs + n++, "/", 0, 0, fs_cb));
355e66f31c5Sopenharmony_ci  ASSERT_OK(uv_fs_write(loop, reqs + n++, -1, &iov, 1, 0, fs_cb));
356e66f31c5Sopenharmony_ci  ASSERT_EQ(n, ARRAY_SIZE(reqs));
357e66f31c5Sopenharmony_ci
358e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_init(loop, &ci.timer_handle));
359e66f31c5Sopenharmony_ci  ASSERT_OK(uv_timer_start(&ci.timer_handle, timer_cb, 10, 0));
360e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
361e66f31c5Sopenharmony_ci  ASSERT_EQ(n, fs_cb_called);
362e66f31c5Sopenharmony_ci  ASSERT_EQ(1, timer_cb_called);
363e66f31c5Sopenharmony_ci
364e66f31c5Sopenharmony_ci
365e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
366e66f31c5Sopenharmony_ci  return 0;
367e66f31c5Sopenharmony_ci}
368e66f31c5Sopenharmony_ci
369e66f31c5Sopenharmony_ci
370e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_single) {
371e66f31c5Sopenharmony_ci  uv_loop_t* loop;
372e66f31c5Sopenharmony_ci  uv_work_t req;
373e66f31c5Sopenharmony_ci
374e66f31c5Sopenharmony_ci  saturate_threadpool();
375e66f31c5Sopenharmony_ci  loop = uv_default_loop();
376e66f31c5Sopenharmony_ci  ASSERT_OK(uv_queue_work(loop, &req, (uv_work_cb) abort, nop_done_cb));
377e66f31c5Sopenharmony_ci  ASSERT_OK(uv_cancel((uv_req_t*) &req));
378e66f31c5Sopenharmony_ci  ASSERT_OK(done_cb_called);
379e66f31c5Sopenharmony_ci  unblock_threadpool();
380e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(loop, UV_RUN_DEFAULT));
381e66f31c5Sopenharmony_ci  ASSERT_EQ(1, done_cb_called);
382e66f31c5Sopenharmony_ci
383e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(loop);
384e66f31c5Sopenharmony_ci  return 0;
385e66f31c5Sopenharmony_ci}
386e66f31c5Sopenharmony_ci
387e66f31c5Sopenharmony_ci
388e66f31c5Sopenharmony_cistatic void after_busy_cb(uv_work_t* req, int status) {
389e66f31c5Sopenharmony_ci  ASSERT_OK(status);
390e66f31c5Sopenharmony_ci  done_cb_called++;
391e66f31c5Sopenharmony_ci}
392e66f31c5Sopenharmony_ci
393e66f31c5Sopenharmony_cistatic void busy_cb(uv_work_t* req) {
394e66f31c5Sopenharmony_ci  uv_sem_post((uv_sem_t*) req->data);
395e66f31c5Sopenharmony_ci  /* Assume that calling uv_cancel() takes less than 10ms. */
396e66f31c5Sopenharmony_ci  uv_sleep(10);
397e66f31c5Sopenharmony_ci}
398e66f31c5Sopenharmony_ci
399e66f31c5Sopenharmony_ciTEST_IMPL(threadpool_cancel_when_busy) {
400e66f31c5Sopenharmony_ci  uv_sem_t sem_lock;
401e66f31c5Sopenharmony_ci  uv_work_t req;
402e66f31c5Sopenharmony_ci
403e66f31c5Sopenharmony_ci  req.data = &sem_lock;
404e66f31c5Sopenharmony_ci
405e66f31c5Sopenharmony_ci  ASSERT_OK(uv_sem_init(&sem_lock, 0));
406e66f31c5Sopenharmony_ci  ASSERT_OK(uv_queue_work(uv_default_loop(), &req, busy_cb, after_busy_cb));
407e66f31c5Sopenharmony_ci
408e66f31c5Sopenharmony_ci  uv_sem_wait(&sem_lock);
409e66f31c5Sopenharmony_ci
410e66f31c5Sopenharmony_ci  ASSERT_EQ(uv_cancel((uv_req_t*) &req), UV_EBUSY);
411e66f31c5Sopenharmony_ci  ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));
412e66f31c5Sopenharmony_ci  ASSERT_EQ(1, done_cb_called);
413e66f31c5Sopenharmony_ci
414e66f31c5Sopenharmony_ci  uv_sem_destroy(&sem_lock);
415e66f31c5Sopenharmony_ci
416e66f31c5Sopenharmony_ci  MAKE_VALGRIND_HAPPY(uv_default_loop());
417e66f31c5Sopenharmony_ci  return 0;
418e66f31c5Sopenharmony_ci}
419