test-loop-handles.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21 
22 /* Tests commented out with XXX are ones that are failing on Linux */
23 
24 /*
25  * Purpose of this test is to check semantics of starting and stopping
26  * prepare, check and idle watchers.
27  *
28  * - A watcher must be able to safely stop or close itself;
29  * - Once a watcher is stopped or closed its callback should never be called.
30  * - If a watcher is closed, it is implicitly stopped and its close_cb should
31  * be called exactly once.
32  * - A watcher can safely start and stop other watchers of the same type.
33  * - Prepare and check watchers are called once per event loop iterations.
34  * - All active idle watchers are queued when the event loop has no more work
35  * to do. This is done repeatedly until all idle watchers are inactive.
36  * - If a watcher starts another watcher of the same type its callback is not
37  * immediately queued. For check and prepare watchers, that means that if
38  * a watcher makes another of the same type active, it'll not be called until
39  * the next event loop iteration. For idle. watchers this means that the
40  * newly activated idle watcher might not be queued immediately.
41  * - Prepare, check, idle watchers keep the event loop alive even when they're
42  * not active.
43  *
44  * This is what the test globally does:
45  *
46  * - prepare_1 is always active and counts event loop iterations. It also
47  * creates and starts prepare_2 every other iteration. Finally it verifies
48  * that no idle watchers are active before polling.
49  * - prepare_2 is started by prepare_1 every other iteration. It immediately
50  * stops itself. It verifies that a watcher is not queued immediately
51  * if created by another watcher of the same type.
52  * - There's a check watcher that stops the event loop after a certain number
53  * of iterations. It starts a varying number of idle_1 watchers.
54  * - Idle_1 watchers stop themselves after being called a few times. All idle_1
55  * watchers try to start the idle_2 watcher if it is not already started or
56  * awaiting its close callback.
57  * - The idle_2 watcher always exists but immediately closes itself after
58  * being started by a check_1 watcher. It verifies that a watcher is
59  * implicitly stopped when closed, and that a watcher can close itself
60  * safely.
61  * - There is a repeating timer. It does not keep the event loop alive
62  * (ev_unref) but makes sure that the loop keeps polling the system for
63  * events.
64  */
65 
66 
67 #include "uv.h"
68 #include "task.h"
69 
70 #include <math.h>
71 
72 
73 #define IDLE_COUNT 7
74 #define ITERATIONS 21
75 #define TIMEOUT 100
76 
77 
80 
82 
85 
87 
88 
89 static int loop_iteration = 0;
90 
91 static int prepare_1_cb_called = 0;
93 
94 static int prepare_2_cb_called = 0;
96 
97 static int check_cb_called = 0;
98 static int check_close_cb_called = 0;
99 
100 static int idle_1_cb_called = 0;
101 static int idle_1_close_cb_called = 0;
102 static int idles_1_active = 0;
103 
104 static int idle_2_cb_called = 0;
105 static int idle_2_close_cb_called = 0;
106 static int idle_2_cb_started = 0;
107 static int idle_2_is_active = 0;
108 
109 
110 static void timer_cb(uv_timer_t* handle) {
112 }
113 
114 
116  fprintf(stderr, "%s", "IDLE_2_CLOSE_CB\n");
117  fflush(stderr);
118 
120 
122 
124  idle_2_is_active = 0;
125 }
126 
127 
128 static void idle_2_cb(uv_idle_t* handle) {
129  fprintf(stderr, "%s", "IDLE_2_CB\n");
130  fflush(stderr);
131 
133 
135 
137 }
138 
139 
140 static void idle_1_cb(uv_idle_t* handle) {
141  int r;
142 
143  fprintf(stderr, "%s", "IDLE_1_CB\n");
144  fflush(stderr);
145 
146  ASSERT(handle != NULL);
147  ASSERT(idles_1_active > 0);
148 
149  /* Init idle_2 and make it active */
152  ASSERT(r == 0);
154  ASSERT(r == 0);
155  idle_2_is_active = 1;
157  }
158 
160 
161  if (idle_1_cb_called % 5 == 0) {
163  ASSERT(r == 0);
164  idles_1_active--;
165  }
166 }
167 
168 
170  fprintf(stderr, "%s", "IDLE_1_CLOSE_CB\n");
171  fflush(stderr);
172 
173  ASSERT(handle != NULL);
174 
176 }
177 
178 
180  fprintf(stderr, "%s", "PREPARE_1_CLOSE_CB");
181  fflush(stderr);
183 
185 }
186 
187 
189  fprintf(stderr, "%s", "CHECK_CLOSE_CB\n");
190  fflush(stderr);
192 
194 }
195 
196 
198  fprintf(stderr, "%s", "PREPARE_2_CLOSE_CB\n");
199  fflush(stderr);
201 
203 }
204 
205 
206 static void check_cb(uv_check_t* handle) {
207  int i, r;
208 
209  fprintf(stderr, "%s", "CHECK_CB\n");
210  fflush(stderr);
212 
213  if (loop_iteration < ITERATIONS) {
214  /* Make some idle watchers active */
215  for (i = 0; i < 1 + (loop_iteration % IDLE_COUNT); i++) {
217  ASSERT(r == 0);
218  idles_1_active++;
219  }
220 
221  } else {
222  /* End of the test - close all handles */
226 
227  for (i = 0; i < IDLE_COUNT; i++) {
229  }
230 
231  /* This handle is closed/recreated every time, close it only if it is
232  * active. */
233  if (idle_2_is_active) {
235  }
236  }
237 
238  check_cb_called++;
239 }
240 
241 
243  int r;
244 
245  fprintf(stderr, "%s", "PREPARE_2_CB\n");
246  fflush(stderr);
248 
249  /* Prepare_2 gets started by prepare_1 when (loop_iteration % 2 == 0), and it
250  * stops itself immediately. A started watcher is not queued until the next
251  * round, so when this callback is made (loop_iteration % 2 == 0) cannot be
252  * true. */
253  ASSERT(loop_iteration % 2 != 0);
254 
256  ASSERT(r == 0);
257 
259 }
260 
261 
263  int r;
264 
265  fprintf(stderr, "%s", "PREPARE_1_CB\n");
266  fflush(stderr);
268 
269  if (loop_iteration % 2 == 0) {
271  ASSERT(r == 0);
272  }
273 
275  loop_iteration++;
276 
277  printf("Loop iteration %d of %d.\n", loop_iteration, ITERATIONS);
278 }
279 
280 
281 TEST_IMPL(loop_handles) {
282  int i;
283  int r;
284 
286  ASSERT(r == 0);
288  ASSERT(r == 0);
289 
291  ASSERT(r == 0);
293  ASSERT(r == 0);
294 
295  /* initialize only, prepare_2 is started by prepare_1_cb */
297  ASSERT(r == 0);
298 
299  for (i = 0; i < IDLE_COUNT; i++) {
300  /* initialize only, idle_1 handles are started by check_cb */
302  ASSERT(r == 0);
303  }
304 
305  /* don't init or start idle_2, both is done by idle_1_cb */
306 
307  /* The timer callback is there to keep the event loop polling unref it as it
308  * is not supposed to keep the loop alive */
310  ASSERT(r == 0);
312  ASSERT(r == 0);
314 
316  ASSERT(r == 0);
317 
319 
322 
325 
328 
329  /* idle_1_cb should be called a lot */
331 
333  ASSERT(idle_2_is_active == 0);
334 
336  return 0;
337 }
uv_prepare_init
UV_EXTERN int uv_prepare_init(uv_loop_t *, uv_prepare_t *prepare)
task.h
uv_prepare_s
Definition: uv.h:804
idle_2_close_cb
static void idle_2_close_cb(uv_handle_t *handle)
Definition: test-loop-handles.c:115
prepare_2_close_cb_called
static int prepare_2_close_cb_called
Definition: test-loop-handles.c:95
printf
_Use_decl_annotations_ int __cdecl printf(const char *_Format,...)
Definition: cs_driver.c:91
idle_2_cb
static void idle_2_cb(uv_idle_t *handle)
Definition: test-loop-handles.c:128
uv_prepare_stop
UV_EXTERN int uv_prepare_stop(uv_prepare_t *prepare)
idle_2_close_cb_called
static int idle_2_close_cb_called
Definition: test-loop-handles.c:105
ASSERT
#define ASSERT(expr)
Definition: task.h:102
prepare_1_close_cb_called
static int prepare_1_close_cb_called
Definition: test-loop-handles.c:92
check_close_cb_called
static int check_close_cb_called
Definition: test-loop-handles.c:98
timer_handle
static uv_timer_t timer_handle
Definition: test-loop-handles.c:86
uv_run
UV_EXTERN int uv_run(uv_loop_t *, uv_run_mode mode)
Definition: unix/core.c:361
check_cb
static void check_cb(uv_check_t *handle)
Definition: test-loop-handles.c:206
uv_is_closing
UV_EXTERN int uv_is_closing(const uv_handle_t *handle)
Definition: unix/core.c:319
uv_unref
UV_EXTERN void uv_unref(uv_handle_t *)
Definition: uv-common.c:522
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
uv_close
UV_EXTERN void uv_close(uv_handle_t *handle, uv_close_cb close_cb)
Definition: unix/core.c:112
uv_idle_stop
UV_EXTERN int uv_idle_stop(uv_idle_t *idle)
idle_1_cb
static void idle_1_cb(uv_idle_t *handle)
Definition: test-loop-handles.c:140
uv_default_loop
UV_EXTERN uv_loop_t * uv_default_loop(void)
Definition: uv-common.c:733
uv_check_s
Definition: uv.h:814
prepare_2_handle
static uv_prepare_t prepare_2_handle
Definition: test-loop-handles.c:79
IDLE_COUNT
#define IDLE_COUNT
Definition: test-loop-handles.c:73
UV_RUN_DEFAULT
@ UV_RUN_DEFAULT
Definition: uv.h:254
idle_1_cb_called
static int idle_1_cb_called
Definition: test-loop-handles.c:100
idle_1_handles
static uv_idle_t idle_1_handles[IDLE_COUNT]
Definition: test-loop-handles.c:83
uv_prepare_start
UV_EXTERN int uv_prepare_start(uv_prepare_t *prepare, uv_prepare_cb cb)
idle_2_is_active
static int idle_2_is_active
Definition: test-loop-handles.c:107
TEST_IMPL
TEST_IMPL(loop_handles)
Definition: test-loop-handles.c:281
uv_timer_s
Definition: uv.h:850
idle_1_close_cb
static void idle_1_close_cb(uv_handle_t *handle)
Definition: test-loop-handles.c:169
prepare_1_cb
static void prepare_1_cb(uv_prepare_t *handle)
Definition: test-loop-handles.c:262
uv_idle_init
UV_EXTERN int uv_idle_init(uv_loop_t *, uv_idle_t *idle)
uv.h
MAKE_VALGRIND_HAPPY
#define MAKE_VALGRIND_HAPPY()
Definition: task.h:229
prepare_2_cb_called
static int prepare_2_cb_called
Definition: test-loop-handles.c:94
uv_idle_start
UV_EXTERN int uv_idle_start(uv_idle_t *idle, uv_idle_cb cb)
ITERATIONS
#define ITERATIONS
Definition: test-loop-handles.c:74
idle_1_close_cb_called
static int idle_1_close_cb_called
Definition: test-loop-handles.c:101
uv_idle_s
Definition: uv.h:824
prepare_2_close_cb
static void prepare_2_close_cb(uv_handle_t *handle)
Definition: test-loop-handles.c:197
check_close_cb
static void check_close_cb(uv_handle_t *handle)
Definition: test-loop-handles.c:188
fix_build_deps.r
r
Definition: fix_build_deps.py:491
prepare_1_cb_called
static int prepare_1_cb_called
Definition: test-loop-handles.c:91
prepare_2_cb
static void prepare_2_cb(uv_prepare_t *handle)
Definition: test-loop-handles.c:242
idles_1_active
static int idles_1_active
Definition: test-loop-handles.c:102
idle_2_handle
static uv_idle_t idle_2_handle
Definition: test-loop-handles.c:84
check_cb_called
static int check_cb_called
Definition: test-loop-handles.c:97
uv_check_init
UV_EXTERN int uv_check_init(uv_loop_t *, uv_check_t *check)
prepare_1_close_cb
static void prepare_1_close_cb(uv_handle_t *handle)
Definition: test-loop-handles.c:179
loop_iteration
static int loop_iteration
Definition: test-loop-handles.c:89
TIMEOUT
#define TIMEOUT
Definition: test-loop-handles.c:75
timer_cb
static void timer_cb(uv_timer_t *handle)
Definition: test-loop-handles.c:110
handle
static csh handle
Definition: test_arm_regression.c:16
uv_handle_s
Definition: uv.h:441
uv_timer_start
UV_EXTERN int uv_timer_start(uv_timer_t *handle, uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
Definition: timer.c:66
uv_timer_init
UV_EXTERN int uv_timer_init(uv_loop_t *, uv_timer_t *handle)
Definition: timer.c:58
idle_2_cb_called
static int idle_2_cb_called
Definition: test-loop-handles.c:104
idle_2_cb_started
static int idle_2_cb_started
Definition: test-loop-handles.c:106
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
prepare_1_handle
static uv_prepare_t prepare_1_handle
Definition: test-loop-handles.c:78
check_handle
static uv_check_t check_handle
Definition: test-loop-handles.c:81
uv_check_start
UV_EXTERN int uv_check_start(uv_check_t *check, uv_check_cb cb)


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:30