blob: ff927385d47ed903e9c04a272917277409684352 [file] [log] [blame]
Craig Tiller9fb89ea2016-03-11 20:12:45 -08001/*
Craig Tillerdbaf05e2016-06-12 22:16:56 -07002 *
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 */
Craig Tiller9fb89ea2016-03-11 20:12:45 -080033
murgatroid99085f9af2016-10-24 09:55:44 -070034/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
35 using that endpoint. Because of various transitive includes in uv.h,
36 including windows.h on Windows, uv.h must be included before other system
37 headers. Therefore, sockaddr.h must always be included first */
murgatroid997871f732016-09-23 13:49:05 -070038#include "src/core/lib/iomgr/sockaddr.h"
39
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020040#include <memory.h>
Craig Tiller57e27432016-03-11 16:53:58 -080041#include <stdio.h>
42
43#include <grpc/grpc.h>
44#include <grpc/support/alloc.h>
Craig Tiller0ce7bec2016-03-11 17:02:07 -080045#include <grpc/support/log.h>
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020046#include <grpc/support/string_util.h>
Craig Tiller57e27432016-03-11 16:53:58 -080047#include <grpc/support/thd.h>
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020048
49#include "src/core/lib/iomgr/exec_ctx.h"
50#include "src/core/lib/iomgr/iomgr.h"
murgatroid997871f732016-09-23 13:49:05 -070051#include "src/core/lib/iomgr/resolve_address.h"
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020052#include "src/core/lib/iomgr/sockaddr_utils.h"
53#include "src/core/lib/iomgr/tcp_server.h"
54
55#include "test/core/util/port.h"
Craig Tiller0ce7bec2016-03-11 17:02:07 -080056#include "test/core/util/test_config.h"
Craig Tiller57e27432016-03-11 16:53:58 -080057
58#define NUM_THREADS 100
Masood Malekghassemi6643ce72016-03-14 14:21:08 -070059#define NUM_OUTER_LOOPS 10
60#define NUM_INNER_LOOPS 10
61#define DELAY_MILLIS 10
62#define POLL_MILLIS 3000
Craig Tiller57e27432016-03-11 16:53:58 -080063
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020064static void *tag(int n) { return (void *)(uintptr_t)n; }
65static int detag(void *p) { return (int)(uintptr_t)p; }
66
67void create_loop_destroy(void *addr) {
Masood Malekghassemi6643ce72016-03-14 14:21:08 -070068 for (int i = 0; i < NUM_OUTER_LOOPS; ++i) {
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020069 grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
Nicolas "Pixel" Noble90f03b52016-04-14 06:17:58 +020070 grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL);
Craig Tiller57e27432016-03-11 16:53:58 -080071
Masood Malekghassemi6643ce72016-03-14 14:21:08 -070072 for (int j = 0; j < NUM_INNER_LOOPS; ++j) {
Robbie Shadeca7effc2017-01-17 09:14:29 -050073 gpr_timespec later_time =
74 grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS);
Craig Tiller57e27432016-03-11 16:53:58 -080075 grpc_connectivity_state state =
76 grpc_channel_check_connectivity_state(chan, 1);
77 grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL);
Robbie Shadeca7effc2017-01-17 09:14:29 -050078 gpr_timespec poll_time =
79 grpc_timeout_milliseconds_to_deadline(POLL_MILLIS);
Masood Malekghassemi6643ce72016-03-14 14:21:08 -070080 GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type ==
81 GRPC_OP_COMPLETE);
Craig Tiller57e27432016-03-11 16:53:58 -080082 }
Masood Malekghassemi6643ce72016-03-14 14:21:08 -070083 grpc_channel_destroy(chan);
84 grpc_completion_queue_destroy(cq);
Craig Tiller57e27432016-03-11 16:53:58 -080085 }
86}
87
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +020088struct server_thread_args {
89 char *addr;
90 grpc_server *server;
91 grpc_completion_queue *cq;
92 grpc_pollset *pollset;
93 gpr_mu *mu;
94 gpr_event ready;
95 gpr_atm stop;
96};
97
98void server_thread(void *vargs) {
Nicolas "Pixel" Noble90f03b52016-04-14 06:17:58 +020099 struct server_thread_args *args = (struct server_thread_args *)vargs;
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200100 grpc_event ev;
101 gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
102 ev = grpc_completion_queue_next(args->cq, deadline, NULL);
103 GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
104 GPR_ASSERT(detag(ev.tag) == 0xd1e);
105}
106
107static void on_connect(grpc_exec_ctx *exec_ctx, void *vargs, grpc_endpoint *tcp,
Craig Tiller29dc4902016-05-20 08:43:48 -0700108 grpc_pollset *accepting_pollset,
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200109 grpc_tcp_server_acceptor *acceptor) {
Mark D. Roth96ba68d2016-12-09 17:21:26 +0000110 gpr_free(acceptor);
Nicolas "Pixel" Noble90f03b52016-04-14 06:17:58 +0200111 struct server_thread_args *args = (struct server_thread_args *)vargs;
Craig Tillercda759d2017-01-27 11:37:37 -0800112 grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200113 grpc_endpoint_destroy(exec_ctx, tcp);
Craig Tiller1aee5362016-05-07 11:26:50 -0700114 GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, NULL));
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200115}
116
117void bad_server_thread(void *vargs) {
Nicolas "Pixel" Noble90f03b52016-04-14 06:17:58 +0200118 struct server_thread_args *args = (struct server_thread_args *)vargs;
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200119
120 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
murgatroid997871f732016-09-23 13:49:05 -0700121 grpc_resolved_address resolved_addr;
122 struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr;
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200123 int port;
Craig Tillerf707d622016-05-06 14:26:12 -0700124 grpc_tcp_server *s;
Craig Tillerd4673482016-09-23 13:50:04 -0700125 grpc_error *error = grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s);
Craig Tillerf707d622016-05-06 14:26:12 -0700126 GPR_ASSERT(error == GRPC_ERROR_NONE);
murgatroid997871f732016-09-23 13:49:05 -0700127 memset(&resolved_addr, 0, sizeof(resolved_addr));
128 addr->ss_family = AF_INET;
murgatroid99dedb9232016-09-26 13:54:04 -0700129 error = grpc_tcp_server_add_port(s, &resolved_addr, &port);
Craig Tiller5352ff12016-05-18 10:44:38 -0700130 GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error));
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200131 GPR_ASSERT(port > 0);
132 gpr_asprintf(&args->addr, "localhost:%d", port);
133
134 grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args);
135 gpr_event_set(&args->ready, (void *)1);
136
137 gpr_mu_lock(args->mu);
138 while (gpr_atm_acq_load(&args->stop) == 0) {
139 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
Nicolas "Pixel" Noble90f03b52016-04-14 06:17:58 +0200140 gpr_timespec deadline =
141 gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN));
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200142
143 grpc_pollset_worker *worker = NULL;
Craig Tiller1aee5362016-05-07 11:26:50 -0700144 if (!GRPC_LOG_IF_ERROR("pollset_work",
145 grpc_pollset_work(&exec_ctx, args->pollset, &worker,
146 now, deadline))) {
147 gpr_atm_rel_store(&args->stop, 1);
148 }
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200149 gpr_mu_unlock(args->mu);
150 grpc_exec_ctx_finish(&exec_ctx);
151 gpr_mu_lock(args->mu);
152 }
153 gpr_mu_unlock(args->mu);
154
155 grpc_tcp_server_unref(&exec_ctx, s);
156
157 grpc_exec_ctx_finish(&exec_ctx);
158
159 gpr_free(args->addr);
160}
161
Craig Tiller653ea752016-04-25 07:40:23 -0700162static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset,
Craig Tillerf707d622016-05-06 14:26:12 -0700163 grpc_error *error) {
Craig Tiller653ea752016-04-25 07:40:23 -0700164 grpc_pollset_destroy(pollset);
165 gpr_free(pollset);
166}
167
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200168int main(int argc, char **argv) {
169 struct server_thread_args args;
170 memset(&args, 0, sizeof(args));
171
Craig Tiller0ce7bec2016-03-11 17:02:07 -0800172 grpc_test_init(argc, argv);
Craig Tiller57e27432016-03-11 16:53:58 -0800173 grpc_init();
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200174
Craig Tiller57e27432016-03-11 16:53:58 -0800175 gpr_thd_id threads[NUM_THREADS];
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200176 gpr_thd_id server;
177
178 char *localhost = gpr_strdup("localhost:54321");
179 gpr_thd_options options = gpr_thd_options_default();
180 gpr_thd_options_set_joinable(&options);
181
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200182 /* First round, no server */
183 gpr_log(GPR_DEBUG, "Wave 1");
Masood Malekghassemi6643ce72016-03-14 14:21:08 -0700184 for (size_t i = 0; i < NUM_THREADS; ++i) {
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200185 gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options);
Craig Tiller57e27432016-03-11 16:53:58 -0800186 }
Masood Malekghassemi6643ce72016-03-14 14:21:08 -0700187 for (size_t i = 0; i < NUM_THREADS; ++i) {
Craig Tiller57e27432016-03-11 16:53:58 -0800188 gpr_thd_join(threads[i]);
189 }
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200190 gpr_free(localhost);
191
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200192 /* Second round, actual grpc server */
193 gpr_log(GPR_DEBUG, "Wave 2");
194 int port = grpc_pick_unused_port_or_die();
195 gpr_asprintf(&args.addr, "localhost:%d", port);
196 args.server = grpc_server_create(NULL, NULL);
197 grpc_server_add_insecure_http2_port(args.server, args.addr);
198 args.cq = grpc_completion_queue_create(NULL);
199 grpc_server_register_completion_queue(args.server, args.cq, NULL);
200 grpc_server_start(args.server);
201 gpr_thd_new(&server, server_thread, &args, &options);
202
203 for (size_t i = 0; i < NUM_THREADS; ++i) {
204 gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options);
205 }
206 for (size_t i = 0; i < NUM_THREADS; ++i) {
207 gpr_thd_join(threads[i]);
208 }
209 grpc_server_shutdown_and_notify(args.server, args.cq, tag(0xd1e));
210
211 gpr_thd_join(server);
212 grpc_server_destroy(args.server);
213 grpc_completion_queue_destroy(args.cq);
214 gpr_free(args.addr);
215
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200216 /* Third round, bogus tcp server */
217 gpr_log(GPR_DEBUG, "Wave 3");
Yuchen Zeng47de64c2017-02-22 19:04:38 -0800218 args.pollset = gpr_zalloc(grpc_pollset_size());
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200219 grpc_pollset_init(args.pollset, &args.mu);
Craig Tiller418b9f92016-04-15 09:06:55 -0700220 gpr_event_init(&args.ready);
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200221 gpr_thd_new(&server, bad_server_thread, &args, &options);
222 gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC));
223
224 for (size_t i = 0; i < NUM_THREADS; ++i) {
225 gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options);
226 }
227 for (size_t i = 0; i < NUM_THREADS; ++i) {
228 gpr_thd_join(threads[i]);
229 }
230
231 gpr_atm_rel_store(&args.stop, 1);
232 gpr_thd_join(server);
Craig Tiller653ea752016-04-25 07:40:23 -0700233 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tiller91031da2016-12-28 15:44:25 -0800234 grpc_pollset_shutdown(&exec_ctx, args.pollset,
235 grpc_closure_create(done_pollset_shutdown, args.pollset,
236 grpc_schedule_on_exec_ctx));
Craig Tiller653ea752016-04-25 07:40:23 -0700237 grpc_exec_ctx_finish(&exec_ctx);
Nicolas "Pixel" Noble04f812b2016-04-13 20:27:51 +0200238
Craig Tiller57e27432016-03-11 16:53:58 -0800239 grpc_shutdown();
240 return 0;
241}