blob: e0675bd9d2c0b7b65109ad7c55ffbb187e6882b5 [file] [log] [blame]
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -08001/*
2 *
3 * Copyright 2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33#include "src/core/lib/iomgr/port.h"
34
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080035/* This test only relevant on linux systems where epoll is available */
36#ifdef GRPC_LINUX_EPOLL
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080037
38#include <errno.h>
39#include <string.h>
40#include <unistd.h>
41
42#include <grpc/support/alloc.h>
43#include <grpc/support/log.h>
44
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080045#include "src/core/lib/iomgr/ev_posix.h"
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080046#include "src/core/lib/iomgr/iomgr.h"
47#include "test/core/util/test_config.h"
48
49/*******************************************************************************
50 * test_pollset_set
51 */
52
53typedef struct test_pollset_set { grpc_pollset_set *pss; } test_pollset_set;
54
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080055void init_test_pollset_sets(test_pollset_set *pollset_sets, int num_pss) {
56 for (int i = 0; i < num_pss; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080057 pollset_sets[i].pss = grpc_pollset_set_create();
58 }
59}
60
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080061void cleanup_test_pollset_sets(test_pollset_set *pollset_sets, int num_pss) {
62 for (int i = 0; i < num_pss; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080063 grpc_pollset_set_destroy(pollset_sets[i].pss);
64 pollset_sets[i].pss = NULL;
65 }
66}
67
68/*******************************************************************************
69 * test_pollset
70 */
71
72typedef struct test_pollset {
73 grpc_pollset *ps;
74 gpr_mu *mu;
75} test_pollset;
76
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080077static void init_test_pollsets(test_pollset *pollsets, int num_pollsets) {
78 for (int i = 0; i < num_pollsets; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080079 pollsets[i].ps = gpr_malloc(grpc_pollset_size());
80 grpc_pollset_init(pollsets[i].ps, &pollsets[i].mu);
81 }
82}
83
84static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p,
85 grpc_error *error) {
86 grpc_pollset_destroy(p);
87}
88
89static void cleanup_test_pollsets(grpc_exec_ctx *exec_ctx,
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080090 test_pollset *pollsets, int num_pollsets) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080091 grpc_closure destroyed;
Sree Kuchibhotla113267b2017-01-25 14:37:19 -080092 for (int i = 0; i < num_pollsets; i++) {
Sree Kuchibhotla645e30a2017-01-20 10:59:15 -080093 grpc_closure_init(&destroyed, destroy_pollset, pollsets[i].ps,
94 grpc_schedule_on_exec_ctx);
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -080095 grpc_pollset_shutdown(exec_ctx, pollsets[i].ps, &destroyed);
96
97 grpc_exec_ctx_flush(exec_ctx);
98 gpr_free(pollsets[i].ps);
99 pollsets[i].ps = NULL;
100 }
101}
102
103/*******************************************************************************
104 * test_fd
105 */
106
107typedef struct test_fd {
108 grpc_fd *fd;
109 grpc_wakeup_fd wakeup_fd;
110
111 bool is_on_readable_called; /* Is on_readable closure is called ? */
112 grpc_closure on_readable; /* Closure to call when this fd is readable */
113} test_fd;
114
115void on_readable(grpc_exec_ctx *exec_ctx, void *tfd, grpc_error *error) {
116 ((test_fd *)tfd)->is_on_readable_called = true;
117}
118
119static void reset_test_fd(grpc_exec_ctx *exec_ctx, test_fd *tfd) {
120 tfd->is_on_readable_called = false;
121
Sree Kuchibhotla645e30a2017-01-20 10:59:15 -0800122 grpc_closure_init(&tfd->on_readable, on_readable, tfd,
123 grpc_schedule_on_exec_ctx);
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800124 grpc_fd_notify_on_read(exec_ctx, tfd->fd, &tfd->on_readable);
125}
126
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800127static void init_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds, int num_fds) {
128 for (int i = 0; i < num_fds; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800129 GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_init(&tfds[i].wakeup_fd));
130 tfds[i].fd = grpc_fd_create(GRPC_WAKEUP_FD_GET_READ_FD(&tfds[i].wakeup_fd),
131 "test_fd");
132 reset_test_fd(exec_ctx, &tfds[i]);
133 }
134}
135
136static void cleanup_test_fds(grpc_exec_ctx *exec_ctx, test_fd *tfds,
137 int num_fds) {
138 int release_fd;
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800139
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800140 for (int i = 0; i < num_fds; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800141 grpc_fd_shutdown(exec_ctx, tfds[i].fd);
142 grpc_exec_ctx_flush(exec_ctx);
143
144 /* grpc_fd_orphan frees the memory allocated for grpc_fd. Normally it also
145 * calls close() on the underlying fd. In our case, we are using
146 * grpc_wakeup_fd and we would like to destroy it ourselves (by calling
147 * grpc_wakeup_fd_destroy). To prevent grpc_fd from calling close() on the
148 * underlying fd, call it with a non-NULL 'release_fd' parameter */
149 grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup");
150 grpc_exec_ctx_flush(exec_ctx);
151
152 grpc_wakeup_fd_destroy(&tfds[i].wakeup_fd);
153 }
154}
155
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800156static void make_test_fds_readable(test_fd *tfds, int num_fds) {
157 for (int i = 0; i < num_fds; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800158 GPR_ASSERT(GRPC_ERROR_NONE == grpc_wakeup_fd_wakeup(&tfds[i].wakeup_fd));
159 }
160}
161
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800162static void verify_readable_and_reset(grpc_exec_ctx *exec_ctx, test_fd *tfds,
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800163 int num_fds) {
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800164 for (int i = 0; i < num_fds; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800165 /* Verify that the on_readable callback was called */
166 GPR_ASSERT(tfds[i].is_on_readable_called);
167
168 /* Reset the tfd[i] structure */
169 GPR_ASSERT(GRPC_ERROR_NONE ==
170 grpc_wakeup_fd_consume_wakeup(&tfds[i].wakeup_fd));
171 reset_test_fd(exec_ctx, &tfds[i]);
172 }
173}
174
175/*******************************************************************************
176 * Main tests
177 */
178
179/* Test some typical scenarios in pollset_set */
180static void pollset_set_test_basic() {
181 /* We construct the following structure for this test:
182 *
183 * +---> FD0 (Added before PSS1, PS1 and PS2 are added to PSS0)
184 * |
185 * +---> FD5 (Added after PSS1, PS1 and PS2 are added to PSS0)
186 * |
187 * |
188 * | +---> FD1 (Added before PSS1 is added to PSS0)
189 * | |
190 * | +---> FD6 (Added after PSS1 is added to PSS0)
191 * | |
192 * +---> PSS1--+ +--> FD2 (Added before PS0 is added to PSS1)
193 * | | |
194 * | +---> PS0---+
195 * | |
196 * PSS0---+ +--> FD7 (Added after PS0 is added to PSS1)
197 * |
198 * |
199 * | +---> FD3 (Added before PS1 is added to PSS0)
200 * | |
201 * +---> PS1---+
202 * | |
203 * | +---> FD8 (Added after PS1 added to PSS0)
204 * |
205 * |
206 * | +---> FD4 (Added before PS2 is added to PSS0)
207 * | |
208 * +---> PS2---+
209 * |
210 * +---> FD9 (Added after PS2 is added to PSS0)
211 */
212 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800213 grpc_pollset_worker *worker;
214 gpr_timespec deadline;
215
216 test_fd tfds[10];
217 test_pollset pollsets[3];
218 test_pollset_set pollset_sets[2];
219 int num_fds = sizeof(tfds) / sizeof(tfds[0]);
220 int num_ps = sizeof(pollsets) / sizeof(pollsets[0]);
221 int num_pss = sizeof(pollset_sets) / sizeof(pollset_sets[0]);
222
223 init_test_fds(&exec_ctx, tfds, num_fds);
224 init_test_pollsets(pollsets, num_ps);
225 init_test_pollset_sets(pollset_sets, num_pss);
226
227 /* Construct the pollset_set/pollset/fd tree (see diagram above) */
228
229 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
230 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
231
232 grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[2].fd);
233 grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[3].fd);
234 grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[4].fd);
235
236 grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss,
237 pollset_sets[1].pss);
238
239 grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps);
240 grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps);
241 grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps);
242
243 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd);
244 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd);
245
246 grpc_pollset_add_fd(&exec_ctx, pollsets[0].ps, tfds[7].fd);
247 grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[8].fd);
248 grpc_pollset_add_fd(&exec_ctx, pollsets[2].ps, tfds[9].fd);
249
250 grpc_exec_ctx_flush(&exec_ctx);
251
252 /* Test that if any FD in the above structure is readable, it is observable by
253 * doing grpc_pollset_work on any pollset
254 *
255 * For every pollset, do the following:
256 * - (Ensure that all FDs are in reset state)
257 * - Make all FDs readable
258 * - Call grpc_pollset_work() on the pollset
259 * - Flush the exec_ctx
260 * - Verify that on_readable call back was called for all FDs (and
261 * reset the FDs)
262 * */
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800263 for (int i = 0; i < num_ps; i++) {
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800264 make_test_fds_readable(tfds, num_fds);
265
266 gpr_mu_lock(pollsets[i].mu);
267 deadline = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(2);
268 GPR_ASSERT(GRPC_ERROR_NONE ==
269 grpc_pollset_work(&exec_ctx, pollsets[i].ps, &worker,
270 gpr_now(GPR_CLOCK_MONOTONIC), deadline));
271 gpr_mu_unlock(pollsets[i].mu);
272
273 grpc_exec_ctx_flush(&exec_ctx);
274
275 verify_readable_and_reset(&exec_ctx, tfds, num_fds);
276 grpc_exec_ctx_flush(&exec_ctx);
277 }
278
279 /* Test tear down */
280 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
281 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[5].fd);
282 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
283 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[6].fd);
284 grpc_exec_ctx_flush(&exec_ctx);
285
286 grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollsets[0].ps);
287 grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[1].ps);
288 grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[0].pss, pollsets[2].ps);
289
290 grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss,
291 pollset_sets[1].pss);
292 grpc_exec_ctx_flush(&exec_ctx);
293
294 cleanup_test_fds(&exec_ctx, tfds, num_fds);
295 cleanup_test_pollsets(&exec_ctx, pollsets, num_ps);
296 cleanup_test_pollset_sets(pollset_sets, num_pss);
297 grpc_exec_ctx_finish(&exec_ctx);
298}
299
300/* Same FD added multiple times to the pollset_set tree */
301void pollset_set_test_dup_fds() {
302 /* We construct the following structure for this test:
303 *
304 * +---> FD0
305 * |
306 * |
307 * PSS0---+
308 * | +---> FD0 (also under PSS0)
309 * | |
310 * +---> PSS1--+ +--> FD1 (also under PSS1)
311 * | |
312 * +---> PS ---+
313 * | |
314 * | +--> FD2
315 * +---> FD1
316 */
317 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
318 grpc_pollset_worker *worker;
319 gpr_timespec deadline;
320
321 test_fd tfds[3];
322 test_pollset pollset;
323 test_pollset_set pollset_sets[2];
324 int num_fds = sizeof(tfds) / sizeof(tfds[0]);
325 int num_ps = 1;
326 int num_pss = sizeof(pollset_sets) / sizeof(pollset_sets[0]);
327
328 init_test_fds(&exec_ctx, tfds, num_fds);
329 init_test_pollsets(&pollset, num_ps);
330 init_test_pollset_sets(pollset_sets, num_pss);
331
332 /* Construct the structure */
333 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
334 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd);
335 grpc_pollset_set_add_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
336
337 grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[1].fd);
338 grpc_pollset_add_fd(&exec_ctx, pollset.ps, tfds[2].fd);
339
340 grpc_pollset_set_add_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps);
341 grpc_pollset_set_add_pollset_set(&exec_ctx, pollset_sets[0].pss,
342 pollset_sets[1].pss);
343
344 /* Test. Make all FDs readable and make sure that can be observed by doing a
345 * grpc_pollset_work on the pollset 'PS' */
346 make_test_fds_readable(tfds, num_fds);
347
348 gpr_mu_lock(pollset.mu);
349 deadline = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(2);
350 GPR_ASSERT(GRPC_ERROR_NONE ==
351 grpc_pollset_work(&exec_ctx, pollset.ps, &worker,
352 gpr_now(GPR_CLOCK_MONOTONIC), deadline));
353 gpr_mu_unlock(pollset.mu);
354 grpc_exec_ctx_flush(&exec_ctx);
355
356 verify_readable_and_reset(&exec_ctx, tfds, num_fds);
357 grpc_exec_ctx_flush(&exec_ctx);
358
359 /* Tear down */
360 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[0].pss, tfds[0].fd);
361 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[0].fd);
362 grpc_pollset_set_del_fd(&exec_ctx, pollset_sets[1].pss, tfds[1].fd);
363
364 grpc_pollset_set_del_pollset(&exec_ctx, pollset_sets[1].pss, pollset.ps);
365 grpc_pollset_set_del_pollset_set(&exec_ctx, pollset_sets[0].pss,
366 pollset_sets[1].pss);
367 grpc_exec_ctx_flush(&exec_ctx);
368
369 cleanup_test_fds(&exec_ctx, tfds, num_fds);
370 cleanup_test_pollsets(&exec_ctx, &pollset, num_ps);
371 cleanup_test_pollset_sets(pollset_sets, num_pss);
372 grpc_exec_ctx_finish(&exec_ctx);
373}
374
375/* Pollset_set with an empty pollset */
376void pollset_set_test_empty_pollset() {
377 /* We construct the following structure for this test:
378 *
379 * +---> PS0 (EMPTY)
380 * |
381 * +---> FD0
382 * |
383 * PSS0---+
384 * | +---> FD1
385 * | |
386 * +---> PS1--+
387 * |
388 * +---> FD2
389 */
390 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
391 grpc_pollset_worker *worker;
392 gpr_timespec deadline;
393
394 test_fd tfds[3];
395 test_pollset pollsets[2];
396 test_pollset_set pollset_set;
397 int num_fds = sizeof(tfds) / sizeof(tfds[0]);
398 int num_ps = sizeof(pollsets) / sizeof(pollsets[0]);
399 int num_pss = 1;
400
401 init_test_fds(&exec_ctx, tfds, num_fds);
402 init_test_pollsets(pollsets, num_ps);
403 init_test_pollset_sets(&pollset_set, num_pss);
404
405 /* Construct the structure */
406 grpc_pollset_set_add_fd(&exec_ctx, pollset_set.pss, tfds[0].fd);
407 grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[1].fd);
408 grpc_pollset_add_fd(&exec_ctx, pollsets[1].ps, tfds[2].fd);
409
410 grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps);
411 grpc_pollset_set_add_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps);
412
413 /* Test. Make all FDs readable and make sure that can be observed by doing
414 * grpc_pollset_work on the empty pollset 'PS0' */
415 make_test_fds_readable(tfds, num_fds);
416
417 gpr_mu_lock(pollsets[0].mu);
418 deadline = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(2);
419 GPR_ASSERT(GRPC_ERROR_NONE ==
420 grpc_pollset_work(&exec_ctx, pollsets[0].ps, &worker,
421 gpr_now(GPR_CLOCK_MONOTONIC), deadline));
422 gpr_mu_unlock(pollsets[0].mu);
423 grpc_exec_ctx_flush(&exec_ctx);
424
425 verify_readable_and_reset(&exec_ctx, tfds, num_fds);
426 grpc_exec_ctx_flush(&exec_ctx);
427
428 /* Tear down */
429 grpc_pollset_set_del_fd(&exec_ctx, pollset_set.pss, tfds[0].fd);
430 grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[0].ps);
431 grpc_pollset_set_del_pollset(&exec_ctx, pollset_set.pss, pollsets[1].ps);
432 grpc_exec_ctx_flush(&exec_ctx);
433
434 cleanup_test_fds(&exec_ctx, tfds, num_fds);
435 cleanup_test_pollsets(&exec_ctx, pollsets, num_ps);
436 cleanup_test_pollset_sets(&pollset_set, num_pss);
437 grpc_exec_ctx_finish(&exec_ctx);
438}
439
440int main(int argc, char **argv) {
Sree Kuchibhotla113267b2017-01-25 14:37:19 -0800441 const char *poll_strategy = grpc_get_poll_strategy_name();
Sree Kuchibhotla645e30a2017-01-20 10:59:15 -0800442 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800443 grpc_test_init(argc, argv);
444 grpc_iomgr_init();
445
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800446 if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) {
447 pollset_set_test_basic();
448 pollset_set_test_dup_fds();
449 pollset_set_test_empty_pollset();
450 } else {
451 gpr_log(GPR_INFO,
452 "Skipping the test. The test is only relevant for 'epoll' "
453 "strategy. and the current strategy is: '%s'",
454 poll_strategy);
455 }
456
Sree Kuchibhotla645e30a2017-01-20 10:59:15 -0800457 grpc_iomgr_shutdown(&exec_ctx);
458 grpc_exec_ctx_finish(&exec_ctx);
Sree Kuchibhotlaef8ef3b2016-12-09 23:03:33 -0800459 return 0;
460}
461#else /* defined(GRPC_LINUX_EPOLL) */
462int main(int argc, char **argv) { return 0; }
463#endif /* !defined(GRPC_LINUX_EPOLL) */