Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Copyright 2015, 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 | */ |
murgatroid99 | 5407089 | 2016-08-08 17:01:18 -0700 | [diff] [blame] | 33 | #include "src/core/lib/iomgr/port.h" |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 34 | |
Sree Kuchibhotla | 76a0795 | 2016-06-22 15:09:06 -0700 | [diff] [blame] | 35 | /* This test only relevant on linux systems where epoll() is available */ |
murgatroid99 | 623dd4f | 2016-08-08 17:31:27 -0700 | [diff] [blame] | 36 | #ifdef GRPC_LINUX_EPOLL |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 37 | #include "src/core/lib/iomgr/ev_epoll_linux.h" |
| 38 | #include "src/core/lib/iomgr/ev_posix.h" |
| 39 | |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 40 | #include <errno.h> |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 41 | #include <string.h> |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 42 | #include <unistd.h> |
| 43 | |
| 44 | #include <grpc/support/alloc.h> |
| 45 | #include <grpc/support/log.h> |
| 46 | |
| 47 | #include "src/core/lib/iomgr/iomgr.h" |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 48 | #include "src/core/lib/iomgr/workqueue.h" |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 49 | #include "test/core/util/test_config.h" |
| 50 | |
| 51 | typedef struct test_pollset { |
| 52 | grpc_pollset *pollset; |
| 53 | gpr_mu *mu; |
| 54 | } test_pollset; |
| 55 | |
| 56 | typedef struct test_fd { |
| 57 | int inner_fd; |
| 58 | grpc_fd *fd; |
| 59 | } test_fd; |
| 60 | |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 61 | /* num_fds should be an even number */ |
| 62 | static void test_fd_init(test_fd *tfds, int *fds, int num_fds) { |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 63 | int i; |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 64 | int r; |
| 65 | |
| 66 | /* Create some dummy file descriptors. Currently using pipe file descriptors |
| 67 | * for this test but we could use any other type of file descriptors. Also, |
| 68 | * since pipe() used in this test creates two fds in each call, num_fds should |
| 69 | * be an even number */ |
| 70 | GPR_ASSERT((num_fds % 2) == 0); |
| 71 | for (i = 0; i < num_fds; i = i + 2) { |
| 72 | r = pipe(fds + i); |
| 73 | if (r != 0) { |
| 74 | gpr_log(GPR_ERROR, "Error in creating pipe. %d (%s)", errno, |
| 75 | strerror(errno)); |
| 76 | return; |
| 77 | } |
| 78 | } |
| 79 | |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 80 | for (i = 0; i < num_fds; i++) { |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 81 | tfds[i].inner_fd = fds[i]; |
| 82 | tfds[i].fd = grpc_fd_create(fds[i], "test_fd"); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 83 | } |
| 84 | } |
| 85 | |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 86 | static void test_fd_cleanup(grpc_exec_ctx *exec_ctx, test_fd *tfds, |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 87 | int num_fds) { |
| 88 | int release_fd; |
| 89 | int i; |
| 90 | |
| 91 | for (i = 0; i < num_fds; i++) { |
Craig Tiller | cda759d | 2017-01-27 11:37:37 -0800 | [diff] [blame] | 92 | grpc_fd_shutdown(exec_ctx, tfds[i].fd, |
| 93 | GRPC_ERROR_CREATE("test_fd_cleanup")); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 94 | grpc_exec_ctx_flush(exec_ctx); |
| 95 | |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 96 | grpc_fd_orphan(exec_ctx, tfds[i].fd, NULL, &release_fd, "test_fd_cleanup"); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 97 | grpc_exec_ctx_flush(exec_ctx); |
| 98 | |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 99 | GPR_ASSERT(release_fd == tfds[i].inner_fd); |
| 100 | close(tfds[i].inner_fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 101 | } |
| 102 | } |
| 103 | |
| 104 | static void test_pollset_init(test_pollset *pollsets, int num_pollsets) { |
| 105 | int i; |
| 106 | for (i = 0; i < num_pollsets; i++) { |
| 107 | pollsets[i].pollset = gpr_malloc(grpc_pollset_size()); |
| 108 | grpc_pollset_init(pollsets[i].pollset, &pollsets[i].mu); |
| 109 | } |
| 110 | } |
| 111 | |
Sree Kuchibhotla | 3131c26 | 2016-06-21 17:28:28 -0700 | [diff] [blame] | 112 | static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, |
| 113 | grpc_error *error) { |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 114 | grpc_pollset_destroy(p); |
| 115 | } |
| 116 | |
| 117 | static void test_pollset_cleanup(grpc_exec_ctx *exec_ctx, |
| 118 | test_pollset *pollsets, int num_pollsets) { |
| 119 | grpc_closure destroyed; |
| 120 | int i; |
| 121 | |
| 122 | for (i = 0; i < num_pollsets; i++) { |
Craig Tiller | d465456 | 2017-01-03 08:45:56 -0800 | [diff] [blame] | 123 | grpc_closure_init(&destroyed, destroy_pollset, pollsets[i].pollset, |
| 124 | grpc_schedule_on_exec_ctx); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 125 | grpc_pollset_shutdown(exec_ctx, pollsets[i].pollset, &destroyed); |
| 126 | |
| 127 | grpc_exec_ctx_flush(exec_ctx); |
| 128 | gpr_free(pollsets[i].pollset); |
| 129 | } |
| 130 | } |
| 131 | |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 132 | static void increment(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { |
| 133 | ++*(int *)arg; |
| 134 | } |
| 135 | |
| 136 | /* |
| 137 | * Validate that merging two workqueues preserves the closures in each queue. |
| 138 | * This is a regression test for a bug in |
| 139 | * polling_island_merge()[ev_epoll_linux.c], where the parent relationship was |
| 140 | * inverted. |
| 141 | */ |
| 142 | static void test_pollset_queue_merge_items() { |
| 143 | grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 144 | const int num_fds = 2; |
| 145 | const int num_pollsets = 2; |
| 146 | const int num_closures = 4; |
| 147 | test_fd tfds[num_fds]; |
| 148 | int fds[num_fds]; |
| 149 | test_pollset pollsets[num_pollsets]; |
| 150 | grpc_closure closures[num_closures]; |
| 151 | int i; |
| 152 | int result = 0; |
| 153 | |
| 154 | test_fd_init(tfds, fds, num_fds); |
| 155 | test_pollset_init(pollsets, num_pollsets); |
| 156 | |
| 157 | /* Two distinct polling islands, each with their own FD and pollset. */ |
| 158 | for (i = 0; i < num_fds; i++) { |
| 159 | grpc_pollset_add_fd(&exec_ctx, pollsets[i].pollset, tfds[i].fd); |
| 160 | grpc_exec_ctx_flush(&exec_ctx); |
| 161 | } |
| 162 | |
| 163 | /* Enqeue the closures, 3 to polling island 0 and 1 to polling island 1. */ |
| 164 | grpc_closure_init( |
| 165 | closures, increment, &result, |
| 166 | grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[0].fd))); |
| 167 | grpc_closure_init( |
| 168 | closures + 1, increment, &result, |
| 169 | grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[0].fd))); |
| 170 | grpc_closure_init( |
| 171 | closures + 2, increment, &result, |
| 172 | grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[0].fd))); |
| 173 | grpc_closure_init( |
| 174 | closures + 3, increment, &result, |
| 175 | grpc_workqueue_scheduler(grpc_fd_get_polling_island(tfds[1].fd))); |
| 176 | for (i = 0; i < num_closures; ++i) { |
| 177 | grpc_closure_sched(&exec_ctx, closures + i, GRPC_ERROR_NONE); |
| 178 | } |
| 179 | |
| 180 | /* Merge the two polling islands. */ |
| 181 | grpc_pollset_add_fd(&exec_ctx, pollsets[0].pollset, tfds[1].fd); |
| 182 | grpc_exec_ctx_flush(&exec_ctx); |
| 183 | |
| 184 | /* |
| 185 | * Execute the closures, verify we see each one execute when executing work on |
| 186 | * the merged polling island. |
| 187 | */ |
| 188 | grpc_pollset_worker *worker = NULL; |
| 189 | for (i = 0; i < num_closures; ++i) { |
| 190 | const gpr_timespec deadline = gpr_time_add( |
| 191 | gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_seconds(2, GPR_TIMESPAN)); |
| 192 | gpr_mu_lock(pollsets[1].mu); |
| 193 | GRPC_LOG_IF_ERROR( |
| 194 | "grpc_pollset_work", |
| 195 | grpc_pollset_work(&exec_ctx, pollsets[1].pollset, &worker, |
| 196 | gpr_now(GPR_CLOCK_MONOTONIC), deadline)); |
| 197 | gpr_mu_unlock(pollsets[1].mu); |
| 198 | } |
| 199 | GPR_ASSERT(result == num_closures); |
| 200 | |
| 201 | test_fd_cleanup(&exec_ctx, tfds, num_fds); |
| 202 | test_pollset_cleanup(&exec_ctx, pollsets, num_pollsets); |
| 203 | grpc_exec_ctx_finish(&exec_ctx); |
| 204 | } |
| 205 | |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 206 | /* |
| 207 | * Cases to test: |
| 208 | * case 1) Polling islands of both fd and pollset are NULL |
| 209 | * case 2) Polling island of fd is NULL but that of pollset is not-NULL |
| 210 | * case 3) Polling island of fd is not-NULL but that of pollset is NULL |
| 211 | * case 4) Polling islands of both fd and pollset are not-NULL and: |
| 212 | * case 4.1) Polling islands of fd and pollset are equal |
| 213 | * case 4.2) Polling islands of fd and pollset are NOT-equal (This results |
| 214 | * in a merge) |
| 215 | * */ |
| 216 | static void test_add_fd_to_pollset() { |
| 217 | grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 218 | const int num_fds = 8; |
| 219 | const int num_pollsets = 4; |
| 220 | test_fd tfds[num_fds]; |
| 221 | int fds[num_fds]; |
| 222 | test_pollset pollsets[num_pollsets]; |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 223 | void *expected_pi = NULL; |
| 224 | int i; |
| 225 | |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 226 | test_fd_init(tfds, fds, num_fds); |
| 227 | test_pollset_init(pollsets, num_pollsets); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 228 | |
| 229 | /*Step 1. |
| 230 | * Create three polling islands (This will exercise test case 1 and 2) with |
| 231 | * the following configuration: |
| 232 | * polling island 0 = { fds:0,1,2, pollsets:0} |
| 233 | * polling island 1 = { fds:3,4, pollsets:1} |
| 234 | * polling island 2 = { fds:5,6,7 pollsets:2} |
| 235 | * |
| 236 | *Step 2. |
| 237 | * Add pollset 3 to polling island 0 (by adding fds 0 and 1 to pollset 3) |
| 238 | * (This will exercise test cases 3 and 4.1). The configuration becomes: |
| 239 | * polling island 0 = { fds:0,1,2, pollsets:0,3} <<< pollset 3 added here |
| 240 | * polling island 1 = { fds:3,4, pollsets:1} |
| 241 | * polling island 2 = { fds:5,6,7 pollsets:2} |
| 242 | * |
| 243 | *Step 3. |
| 244 | * Merge polling islands 0 and 1 by adding fd 0 to pollset 1 (This will |
| 245 | * exercise test case 4.2). The configuration becomes: |
| 246 | * polling island (merged) = {fds: 0,1,2,3,4, pollsets: 0,1,3} |
| 247 | * polling island 2 = {fds: 5,6,7 pollsets: 2} |
| 248 | * |
| 249 | *Step 4. |
| 250 | * Finally do one more merge by adding fd 3 to pollset 2. |
| 251 | * polling island (merged) = {fds: 0,1,2,3,4,5,6,7, pollsets: 0,1,2,3} |
| 252 | */ |
| 253 | |
| 254 | /* == Step 1 == */ |
| 255 | for (i = 0; i <= 2; i++) { |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 256 | grpc_pollset_add_fd(&exec_ctx, pollsets[0].pollset, tfds[i].fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 257 | grpc_exec_ctx_flush(&exec_ctx); |
| 258 | } |
| 259 | |
| 260 | for (i = 3; i <= 4; i++) { |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 261 | grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[i].fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 262 | grpc_exec_ctx_flush(&exec_ctx); |
| 263 | } |
| 264 | |
| 265 | for (i = 5; i <= 7; i++) { |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 266 | grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[i].fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 267 | grpc_exec_ctx_flush(&exec_ctx); |
| 268 | } |
| 269 | |
| 270 | /* == Step 2 == */ |
| 271 | for (i = 0; i <= 1; i++) { |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 272 | grpc_pollset_add_fd(&exec_ctx, pollsets[3].pollset, tfds[i].fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 273 | grpc_exec_ctx_flush(&exec_ctx); |
| 274 | } |
| 275 | |
| 276 | /* == Step 3 == */ |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 277 | grpc_pollset_add_fd(&exec_ctx, pollsets[1].pollset, tfds[0].fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 278 | grpc_exec_ctx_flush(&exec_ctx); |
| 279 | |
| 280 | /* == Step 4 == */ |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 281 | grpc_pollset_add_fd(&exec_ctx, pollsets[2].pollset, tfds[3].fd); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 282 | grpc_exec_ctx_flush(&exec_ctx); |
| 283 | |
| 284 | /* All polling islands are merged at this point */ |
| 285 | |
| 286 | /* Compare Fd:0's polling island with that of all other Fds */ |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 287 | expected_pi = grpc_fd_get_polling_island(tfds[0].fd); |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 288 | for (i = 1; i < num_fds; i++) { |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 289 | GPR_ASSERT(grpc_are_polling_islands_equal( |
Sree Kuchibhotla | a2dd838 | 2016-06-22 10:26:03 -0700 | [diff] [blame] | 290 | expected_pi, grpc_fd_get_polling_island(tfds[i].fd))); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | /* Compare Fd:0's polling island with that of all other pollsets */ |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 294 | for (i = 0; i < num_pollsets; i++) { |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 295 | GPR_ASSERT(grpc_are_polling_islands_equal( |
| 296 | expected_pi, grpc_pollset_get_polling_island(pollsets[i].pollset))); |
| 297 | } |
| 298 | |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 299 | test_fd_cleanup(&exec_ctx, tfds, num_fds); |
| 300 | test_pollset_cleanup(&exec_ctx, pollsets, num_pollsets); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 301 | grpc_exec_ctx_finish(&exec_ctx); |
| 302 | } |
| 303 | |
| 304 | int main(int argc, char **argv) { |
| 305 | const char *poll_strategy = NULL; |
| 306 | grpc_test_init(argc, argv); |
| 307 | grpc_iomgr_init(); |
| 308 | |
| 309 | poll_strategy = grpc_get_poll_strategy_name(); |
| 310 | if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) { |
| 311 | test_add_fd_to_pollset(); |
Harvey Tuch | daa9f45 | 2016-11-21 15:42:49 -0500 | [diff] [blame] | 312 | test_pollset_queue_merge_items(); |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 313 | } else { |
| 314 | gpr_log(GPR_INFO, |
| 315 | "Skipping the test. The test is only relevant for 'epoll' " |
| 316 | "strategy. and the current strategy is: '%s'", |
| 317 | poll_strategy); |
| 318 | } |
Craig Tiller | 7c70b6c | 2017-01-23 07:48:42 -0800 | [diff] [blame] | 319 | |
Craig Tiller | 7885d1a | 2016-11-17 14:07:45 -0800 | [diff] [blame] | 320 | { |
| 321 | grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
| 322 | grpc_iomgr_shutdown(&exec_ctx); |
| 323 | grpc_exec_ctx_finish(&exec_ctx); |
| 324 | } |
Sree Kuchibhotla | 2e12db9 | 2016-06-16 16:53:59 -0700 | [diff] [blame] | 325 | return 0; |
| 326 | } |
murgatroid99 | 623dd4f | 2016-08-08 17:31:27 -0700 | [diff] [blame] | 327 | #else /* defined(GRPC_LINUX_EPOLL) */ |
Sree Kuchibhotla | fcb304f | 2016-06-22 15:25:41 -0700 | [diff] [blame] | 328 | int main(int argc, char **argv) { return 0; } |
murgatroid99 | 623dd4f | 2016-08-08 17:31:27 -0700 | [diff] [blame] | 329 | #endif /* !defined(GRPC_LINUX_EPOLL) */ |