static void test_values(void) { int i; gpr_timespec x = gpr_time_0(GPR_CLOCK_REALTIME); GPR_ASSERT(x.tv_sec == 0 && x.tv_nsec == 0); x = gpr_inf_future(GPR_CLOCK_REALTIME); fprintf(stderr, "far future "); i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); fprintf(stderr, "\n"); GPR_ASSERT(x.tv_sec == INT64_MAX); fprintf(stderr, "far future "); ts_to_s(x, &to_fp, stderr); fprintf(stderr, "\n"); x = gpr_inf_past(GPR_CLOCK_REALTIME); fprintf(stderr, "far past "); i_to_s(x.tv_sec, 16, 16, &to_fp, stderr); fprintf(stderr, "\n"); GPR_ASSERT(x.tv_sec == INT64_MIN); fprintf(stderr, "far past "); ts_to_s(x, &to_fp, stderr); fprintf(stderr, "\n"); for (i = 1; i != 1000 * 1000 * 1000; i *= 10) { x = gpr_time_from_micros(i, GPR_TIMESPAN); GPR_ASSERT(x.tv_sec == i / GPR_US_PER_SEC && x.tv_nsec == (i % GPR_US_PER_SEC) * GPR_NS_PER_US); x = gpr_time_from_nanos(i, GPR_TIMESPAN); GPR_ASSERT(x.tv_sec == i / GPR_NS_PER_SEC && x.tv_nsec == (i % GPR_NS_PER_SEC)); x = gpr_time_from_millis(i, GPR_TIMESPAN); GPR_ASSERT(x.tv_sec == i / GPR_MS_PER_SEC && x.tv_nsec == (i % GPR_MS_PER_SEC) * GPR_NS_PER_MS); } /* Test possible overflow in conversion of -ve values. */ x = gpr_time_from_micros(-(LONG_MAX - 999997), GPR_TIMESPAN); GPR_ASSERT(x.tv_sec < 0); GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); x = gpr_time_from_nanos(-(LONG_MAX - 999999997), GPR_TIMESPAN); GPR_ASSERT(x.tv_sec < 0); GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); x = gpr_time_from_millis(-(LONG_MAX - 997), GPR_TIMESPAN); GPR_ASSERT(x.tv_sec < 0); GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC); /* Test general -ve values. */ for (i = -1; i > -1000 * 1000 * 1000; i *= 7) { x = gpr_time_from_micros(i, GPR_TIMESPAN); GPR_ASSERT(x.tv_sec * GPR_US_PER_SEC + x.tv_nsec / GPR_NS_PER_US == i); x = gpr_time_from_nanos(i, GPR_TIMESPAN); GPR_ASSERT(x.tv_sec * GPR_NS_PER_SEC + x.tv_nsec == i); x = gpr_time_from_millis(i, GPR_TIMESPAN); GPR_ASSERT(x.tv_sec * GPR_MS_PER_SEC + x.tv_nsec / GPR_NS_PER_MS == i); } }
// Mocks posix poll() function int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) { int res = 0; gpr_timespec poll_time; gpr_mu_lock(&poll_mu); GPR_ASSERT(nfds == 3); GPR_ASSERT(fds[0].fd == 20); GPR_ASSERT(fds[1].fd == 30); GPR_ASSERT(fds[2].fd == 50); GPR_ASSERT(fds[0].events == (POLLIN | POLLHUP)); GPR_ASSERT(fds[1].events == (POLLIN | POLLHUP)); GPR_ASSERT(fds[2].events == POLLIN); if (timeout < 0) { poll_time = gpr_inf_future(GPR_CLOCK_REALTIME); } else { poll_time = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(timeout, GPR_TIMESPAN)); } if (socket_event || !gpr_cv_wait(&poll_cv, &poll_mu, poll_time)) { fds[0].revents = POLLIN; res = 1; } gpr_mu_unlock(&poll_mu); return res; }
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) { gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); grpc_pollset_kick(&cc->pollset); grpc_pollset_work(&cc->pollset, gpr_time_add(gpr_now(), gpr_time_from_millis(100))); gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); }
// Either start polling channel connection state or signal that it's free to // destroy. // Not safe to call while a channel's connection state is polled. static void grpc_rb_channel_try_register_connection_polling( grpc_rb_channel *wrapper) { grpc_connectivity_state conn_state; gpr_timespec sleep_time = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN)); GPR_ASSERT(wrapper); GPR_ASSERT(wrapper->wrapped); gpr_mu_lock(&wrapper->channel_mu); if (wrapper->request_safe_destroy) { wrapper->safe_to_destroy = 1; gpr_cv_broadcast(&wrapper->channel_cv); gpr_mu_unlock(&wrapper->channel_mu); return; } gpr_mu_lock(&global_connection_polling_mu); conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); if (conn_state != wrapper->current_connectivity_state) { wrapper->current_connectivity_state = conn_state; gpr_cv_broadcast(&wrapper->channel_cv); } // avoid posting work to the channel polling cq if it's been shutdown if (!abort_channel_polling && conn_state != GRPC_CHANNEL_SHUTDOWN) { grpc_channel_watch_connectivity_state( wrapper->wrapped, conn_state, sleep_time, channel_polling_cq, wrapper); } else { wrapper->safe_to_destroy = 1; gpr_cv_broadcast(&wrapper->channel_cv); } gpr_mu_unlock(&global_connection_polling_mu); gpr_mu_unlock(&wrapper->channel_mu); }
void grpc_iomgr_shutdown(void) { grpc_iomgr_object *obj; grpc_iomgr_closure *closure; gpr_timespec shutdown_deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); gpr_mu_lock(&g_mu); g_shutdown = 1; while (g_cbs_head || g_root_object.next != &g_root_object) { size_t nobjs = count_objects(); gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", nobjs, g_cbs_head ? " and executing final callbacks" : ""); if (g_cbs_head) { do { closure = g_cbs_head; g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); closure->cb(closure->cb_arg, 0); gpr_mu_lock(&g_mu); } while (g_cbs_head); continue; } if (nobjs > 0) { int timeout = 0; gpr_timespec short_deadline = gpr_time_add(gpr_now(), gpr_time_from_millis(100)); while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) { if (gpr_time_cmp(gpr_now(), shutdown_deadline) > 0) { timeout = 1; break; } } if (timeout) { gpr_log(GPR_DEBUG, "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { gpr_log(GPR_DEBUG, "LEAKED OBJECT: %s", obj->name); } break; } } } gpr_mu_unlock(&g_mu); grpc_kick_poller(); gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future); grpc_iomgr_platform_shutdown(); grpc_alarm_list_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); }
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { size_t i; int port = 0; portreq *pr = arg; int failed = 0; grpc_httpcli_response *response = &pr->response; if (error != GRPC_ERROR_NONE) { failed = 1; const char *msg = grpc_error_string(error); gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg); grpc_error_free_string(msg); } else if (response->status != 200) { failed = 1; gpr_log(GPR_DEBUG, "failed port pick from server: status=%d", response->status); } if (failed) { grpc_httpcli_request req; memset(&req, 0, sizeof(req)); GPR_ASSERT(pr->retries < 10); gpr_sleep_until(gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis( (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)), GPR_TIMESPAN))); pr->retries++; req.host = pr->server; req.http.path = "/get"; grpc_http_response_destroy(&pr->response); memset(&pr->response, 0, sizeof(pr->response)); grpc_resource_quota *resource_quota = grpc_resource_quota_create("port_server_client/pick_retry"); grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, resource_quota, &req, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), grpc_closure_create(got_port_from_server, pr), &pr->response); grpc_resource_quota_internal_unref(exec_ctx, resource_quota); return; } GPR_ASSERT(response); GPR_ASSERT(response->status == 200); for (i = 0; i < response->body_length; i++) { GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9'); port = port * 10 + response->body[i] - '0'; } GPR_ASSERT(port > 1024); gpr_mu_lock(pr->mu); pr->port = port; GRPC_LOG_IF_ERROR( "pollset_kick", grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL)); gpr_mu_unlock(pr->mu); }
/* Cleaning up a list with pending alarms. */ void destruction_test(void) { grpc_alarm alarms[5]; grpc_alarm_list_init(gpr_time_0); memset(cb_called, 0, sizeof(cb_called)); grpc_alarm_init(&alarms[0], gpr_time_from_millis(100), cb, (void *)(gpr_intptr)0, gpr_time_0); grpc_alarm_init(&alarms[1], gpr_time_from_millis(3), cb, (void *)(gpr_intptr)1, gpr_time_0); grpc_alarm_init(&alarms[2], gpr_time_from_millis(100), cb, (void *)(gpr_intptr)2, gpr_time_0); grpc_alarm_init(&alarms[3], gpr_time_from_millis(3), cb, (void *)(gpr_intptr)3, gpr_time_0); grpc_alarm_init(&alarms[4], gpr_time_from_millis(1), cb, (void *)(gpr_intptr)4, gpr_time_0); GPR_ASSERT(1 == grpc_alarm_check(NULL, gpr_time_from_millis(2), NULL)); GPR_ASSERT(1 == cb_called[4][1]); grpc_alarm_cancel(&alarms[0]); grpc_alarm_cancel(&alarms[3]); GPR_ASSERT(1 == cb_called[0][0]); GPR_ASSERT(1 == cb_called[3][0]); grpc_alarm_list_shutdown(); GPR_ASSERT(1 == cb_called[1][0]); GPR_ASSERT(1 == cb_called[2][0]); }
void test_encoding(void) { LOG_TEST("test_encoding"); assert_encodes_as(gpr_time_from_micros(-1, GPR_TIMESPAN), "1n"); assert_encodes_as(gpr_time_from_seconds(-10, GPR_TIMESPAN), "1n"); assert_encodes_as(gpr_time_from_nanos(10, GPR_TIMESPAN), "10n"); assert_encodes_as(gpr_time_from_nanos(999999999, GPR_TIMESPAN), "1S"); assert_encodes_as(gpr_time_from_micros(1, GPR_TIMESPAN), "1u"); assert_encodes_as(gpr_time_from_micros(10, GPR_TIMESPAN), "10u"); assert_encodes_as(gpr_time_from_micros(100, GPR_TIMESPAN), "100u"); assert_encodes_as(gpr_time_from_micros(890, GPR_TIMESPAN), "890u"); assert_encodes_as(gpr_time_from_micros(900, GPR_TIMESPAN), "900u"); assert_encodes_as(gpr_time_from_micros(901, GPR_TIMESPAN), "901u"); assert_encodes_as(gpr_time_from_millis(1, GPR_TIMESPAN), "1m"); assert_encodes_as(gpr_time_from_millis(2, GPR_TIMESPAN), "2m"); assert_encodes_as(gpr_time_from_micros(10001, GPR_TIMESPAN), "10100u"); assert_encodes_as(gpr_time_from_micros(999999, GPR_TIMESPAN), "1S"); assert_encodes_as(gpr_time_from_millis(1000, GPR_TIMESPAN), "1S"); assert_encodes_as(gpr_time_from_millis(2000, GPR_TIMESPAN), "2S"); assert_encodes_as(gpr_time_from_millis(2500, GPR_TIMESPAN), "2500m"); assert_encodes_as(gpr_time_from_millis(59900, GPR_TIMESPAN), "59900m"); assert_encodes_as(gpr_time_from_seconds(50, GPR_TIMESPAN), "50S"); assert_encodes_as(gpr_time_from_seconds(59, GPR_TIMESPAN), "59S"); assert_encodes_as(gpr_time_from_seconds(60, GPR_TIMESPAN), "1M"); assert_encodes_as(gpr_time_from_seconds(80, GPR_TIMESPAN), "80S"); assert_encodes_as(gpr_time_from_seconds(90, GPR_TIMESPAN), "90S"); assert_encodes_as(gpr_time_from_minutes(2, GPR_TIMESPAN), "2M"); assert_encodes_as(gpr_time_from_minutes(20, GPR_TIMESPAN), "20M"); assert_encodes_as(gpr_time_from_hours(1, GPR_TIMESPAN), "1H"); assert_encodes_as(gpr_time_from_hours(10, GPR_TIMESPAN), "10H"); assert_encodes_as(gpr_time_from_seconds(1000000000, GPR_TIMESPAN), "1000000000S"); }
void test_encoding(void) { LOG_TEST(); assert_encodes_as(gpr_time_from_micros(-1), "1n"); assert_encodes_as(gpr_time_from_seconds(-10), "1n"); assert_encodes_as(gpr_time_from_nanos(10), "10n"); assert_encodes_as(gpr_time_from_nanos(999999999), "1S"); assert_encodes_as(gpr_time_from_micros(1), "1u"); assert_encodes_as(gpr_time_from_micros(10), "10u"); assert_encodes_as(gpr_time_from_micros(100), "100u"); assert_encodes_as(gpr_time_from_micros(890), "890u"); assert_encodes_as(gpr_time_from_micros(900), "900u"); assert_encodes_as(gpr_time_from_micros(901), "901u"); assert_encodes_as(gpr_time_from_millis(1), "1m"); assert_encodes_as(gpr_time_from_millis(2), "2m"); assert_encodes_as(gpr_time_from_micros(10001), "10100u"); assert_encodes_as(gpr_time_from_micros(999999), "1S"); assert_encodes_as(gpr_time_from_millis(1000), "1S"); assert_encodes_as(gpr_time_from_millis(2000), "2S"); assert_encodes_as(gpr_time_from_millis(2500), "2500m"); assert_encodes_as(gpr_time_from_millis(59900), "59900m"); assert_encodes_as(gpr_time_from_seconds(50), "50S"); assert_encodes_as(gpr_time_from_seconds(59), "59S"); assert_encodes_as(gpr_time_from_seconds(60), "1M"); assert_encodes_as(gpr_time_from_seconds(80), "80S"); assert_encodes_as(gpr_time_from_seconds(90), "90S"); assert_encodes_as(gpr_time_from_minutes(2), "2M"); assert_encodes_as(gpr_time_from_minutes(20), "20M"); assert_encodes_as(gpr_time_from_hours(1), "1H"); assert_encodes_as(gpr_time_from_hours(10), "10H"); assert_encodes_as(gpr_time_from_seconds(1000000000), "1000000000S"); }
gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) { const double new_timeout_millis = backoff->multiplier * (double)backoff->current_timeout_millis; backoff->current_timeout_millis = GPR_MIN((int64_t)new_timeout_millis, backoff->max_timeout_millis); const double jitter_range_width = backoff->jitter * new_timeout_millis; const double jitter = (2 * generate_uniform_random_number(&backoff->rng_state) - 1) * jitter_range_width; backoff->current_timeout_millis = (int64_t)((double)(backoff->current_timeout_millis) + jitter); const gpr_timespec current_deadline = gpr_time_add( now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN)); const gpr_timespec min_deadline = gpr_time_add( now, gpr_time_from_millis(backoff->min_timeout_millis, GPR_TIMESPAN)); return gpr_time_max(current_deadline, min_deadline); }
gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) { double new_timeout_millis = backoff->multiplier * (double)backoff->current_timeout_millis; double jitter_range = backoff->jitter * new_timeout_millis; double jitter = (2 * generate_uniform_random_number(&backoff->rng_state) - 1) * jitter_range; backoff->current_timeout_millis = GPR_CLAMP((int64_t)(new_timeout_millis + jitter), backoff->min_timeout_millis, backoff->max_timeout_millis); return gpr_time_add( now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN)); }
void grpc_iomgr_shutdown(void) { delayed_callback *cb; gpr_timespec shutdown_deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(10)); gpr_mu_lock(&g_mu); g_shutdown = 1; while (g_cbs_head || g_refs) { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed%s", g_refs, g_cbs_head ? " and executing final callbacks" : ""); while (g_cbs_head) { cb = g_cbs_head; g_cbs_head = cb->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); cb->cb(cb->cb_arg, 0); gpr_free(cb); gpr_mu_lock(&g_mu); } if (g_refs) { int timeout = 0; gpr_timespec short_deadline = gpr_time_add(gpr_now(), gpr_time_from_millis(100)); while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) { if (gpr_time_cmp(gpr_now(), shutdown_deadline) > 0) { timeout = 1; break; } } if (timeout) { gpr_log(GPR_DEBUG, "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", g_refs); break; } } } gpr_mu_unlock(&g_mu); grpc_kick_poller(); gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future); grpc_iomgr_platform_shutdown(); grpc_alarm_list_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_cv); gpr_cv_destroy(&g_rcv); }
/* Calls grpc_completion_queue_next without holding the ruby GIL */ static void *grpc_rb_completion_queue_next_no_gil(void *param) { next_call_stack *const next_call = (next_call_stack*)param; gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN); gpr_timespec deadline; do { deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment); next_call->event = grpc_completion_queue_next(next_call->cq, deadline, NULL); if (next_call->event.type != GRPC_QUEUE_TIMEOUT || gpr_time_cmp(deadline, next_call->timeout) > 0) { break; } } while (!next_call->interrupted); return NULL; }
static void add_test(void) { gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); int i; grpc_alarm alarms[20]; grpc_alarm_list_init(start); memset(cb_called, 0, sizeof(cb_called)); /* 10 ms alarms. will expire in the current epoch */ for (i = 0; i < 10; i++) { grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(10)), cb, (void *)(gpr_intptr)i, start); } /* 1010 ms alarms. will expire in the next epoch */ for (i = 10; i < 20; i++) { grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(1010)), cb, (void *)(gpr_intptr)i, start); } /* collect alarms. Only the first batch should be ready. */ GPR_ASSERT(10 == grpc_alarm_check( NULL, gpr_time_add(start, gpr_time_from_millis(500)), NULL)); for (i = 0; i < 20; i++) { GPR_ASSERT(cb_called[i][1] == (i < 10)); GPR_ASSERT(cb_called[i][0] == 0); } GPR_ASSERT(0 == grpc_alarm_check( NULL, gpr_time_add(start, gpr_time_from_millis(600)), NULL)); for (i = 0; i < 30; i++) { GPR_ASSERT(cb_called[i][1] == (i < 10)); GPR_ASSERT(cb_called[i][0] == 0); } /* collect the rest of the alarms */ GPR_ASSERT(10 == grpc_alarm_check( NULL, gpr_time_add(start, gpr_time_from_millis(1500)), NULL)); for (i = 0; i < 30; i++) { GPR_ASSERT(cb_called[i][1] == (i < 20)); GPR_ASSERT(cb_called[i][0] == 0); } GPR_ASSERT(0 == grpc_alarm_check( NULL, gpr_time_add(start, gpr_time_from_millis(1600)), NULL)); for (i = 0; i < 30; i++) { GPR_ASSERT(cb_called[i][1] == (i < 20)); GPR_ASSERT(cb_called[i][0] == 0); } grpc_alarm_list_shutdown(); }
void grpc_server_destroy(grpc_server *server) { channel_data *c; listener *l; size_t i; call_data *calld; gpr_mu_lock(&server->mu); if (!server->shutdown) { gpr_mu_unlock(&server->mu); grpc_server_shutdown(server); gpr_mu_lock(&server->mu); } while (server->listeners_destroyed != num_listeners(server)) { for (i = 0; i < server->cq_count; i++) { gpr_mu_unlock(&server->mu); grpc_cq_hack_spin_pollset(server->cqs[i]); gpr_mu_lock(&server->mu); } gpr_cv_wait(&server->cv, &server->mu, gpr_time_add(gpr_now(), gpr_time_from_millis(100))); } while (server->listeners) { l = server->listeners; server->listeners = l->next; gpr_free(l); } while ((calld = call_list_remove_head(&server->lists[PENDING_START], PENDING_START)) != NULL) { gpr_log(GPR_DEBUG, "server destroys call %p", calld->call); calld->state = ZOMBIED; grpc_iomgr_add_callback( kill_zombie, grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); } for (c = server->root_channel_data.next; c != &server->root_channel_data; c = c->next) { shutdown_channel(c); } gpr_mu_unlock(&server->mu); server_unref(server); }
static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, const grpc_httpcli_response *response) { size_t i; int port = 0; portreq *pr = arg; int failed = 0; if (!response) { failed = 1; gpr_log(GPR_DEBUG, "failed port pick from server: retrying [response=NULL]"); } else if (response->status != 200) { failed = 1; gpr_log(GPR_DEBUG, "failed port pick from server: status=%d", response->status); } if (failed) { grpc_httpcli_request req; memset(&req, 0, sizeof(req)); GPR_ASSERT(pr->retries < 10); gpr_sleep_until(gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis( (int64_t)(1000.0 * (1 + pow(1.3, pr->retries) * rand() / RAND_MAX)), GPR_TIMESPAN))); pr->retries++; req.host = pr->server; req.http.path = "/get"; grpc_httpcli_get(exec_ctx, pr->ctx, &pr->pops, &req, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server, pr); return; } GPR_ASSERT(response); GPR_ASSERT(response->status == 200); for (i = 0; i < response->body_length; i++) { GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9'); port = port * 10 + response->body[i] - '0'; } GPR_ASSERT(port > 1024); gpr_mu_lock(pr->mu); pr->port = port; grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL); gpr_mu_unlock(pr->mu); }
static void sched_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep, gpr_timespec deadline) { if (gpr_time_cmp(deadline, gpr_now(deadline.clock_type)) < 0) { *ep = NULL; grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL); return; } future_connect *fc = gpr_malloc(sizeof(*fc)); fc->closure = closure; fc->ep = ep; fc->deadline = deadline; grpc_timer_init(exec_ctx, &fc->timer, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(1, GPR_TIMESPAN)), do_connect, fc, gpr_now(GPR_CLOCK_MONOTONIC)); }
void bad_server_thread(void *vargs) { struct server_thread_args *args = (struct server_thread_args *)vargs; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_resolved_address resolved_addr; struct sockaddr_storage *addr = (struct sockaddr_storage *)resolved_addr.addr; int port; grpc_tcp_server *s; grpc_error *error = grpc_tcp_server_create(&exec_ctx, NULL, NULL, &s); GPR_ASSERT(error == GRPC_ERROR_NONE); memset(&resolved_addr, 0, sizeof(resolved_addr)); addr->ss_family = AF_INET; error = grpc_tcp_server_add_port(s, &resolved_addr, &port); GPR_ASSERT(GRPC_LOG_IF_ERROR("grpc_tcp_server_add_port", error)); GPR_ASSERT(port > 0); gpr_asprintf(&args->addr, "localhost:%d", port); grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args); gpr_event_set(&args->ready, (void *)1); gpr_mu_lock(args->mu); while (gpr_atm_acq_load(&args->stop) == 0) { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec deadline = gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN)); grpc_pollset_worker *worker = NULL; if (!GRPC_LOG_IF_ERROR("pollset_work", grpc_pollset_work(&exec_ctx, args->pollset, &worker, now, deadline))) { gpr_atm_rel_store(&args->stop, 1); } gpr_mu_unlock(args->mu); grpc_exec_ctx_finish(&exec_ctx); gpr_mu_lock(args->mu); } gpr_mu_unlock(args->mu); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); gpr_free(args->addr); }
/* Execute followup callbacks continuously. Other threads may check in and help during pollset_work() */ static void background_callback_executor(void *ignored) { gpr_mu_lock(&g_mu); while (!g_shutdown) { gpr_timespec deadline = gpr_inf_future; gpr_timespec short_deadline = gpr_time_add(gpr_now(), gpr_time_from_millis(100)); if (g_cbs_head) { grpc_iomgr_closure *closure = g_cbs_head; g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); closure->cb(closure->cb_arg, closure->success); gpr_mu_lock(&g_mu); } else if (grpc_alarm_check(&g_mu, gpr_now(), &deadline)) { } else { gpr_mu_unlock(&g_mu); gpr_sleep_until(gpr_time_min(short_deadline, deadline)); gpr_mu_lock(&g_mu); } } gpr_mu_unlock(&g_mu); gpr_event_set(&g_background_callback_executor_done, (void *)1); }
void bad_server_thread(void *vargs) { struct server_thread_args *args = (struct server_thread_args *)vargs; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); int port; grpc_tcp_server *s = grpc_tcp_server_create(NULL); memset(&addr, 0, sizeof(addr)); addr.ss_family = AF_INET; port = grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, addr_len); GPR_ASSERT(port > 0); gpr_asprintf(&args->addr, "localhost:%d", port); grpc_tcp_server_start(&exec_ctx, s, &args->pollset, 1, on_connect, args); gpr_event_set(&args->ready, (void *)1); gpr_mu_lock(args->mu); while (gpr_atm_acq_load(&args->stop) == 0) { gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec deadline = gpr_time_add(now, gpr_time_from_millis(100, GPR_TIMESPAN)); grpc_pollset_worker *worker = NULL; grpc_pollset_work(&exec_ctx, args->pollset, &worker, now, deadline); gpr_mu_unlock(args->mu); grpc_exec_ctx_finish(&exec_ctx); gpr_mu_lock(args->mu); } gpr_mu_unlock(args->mu); grpc_tcp_server_unref(&exec_ctx, s); grpc_exec_ctx_finish(&exec_ctx); gpr_free(args->addr); }
static void test_no_jitter_backoff(void) { gpr_backoff backoff; gpr_backoff_init(&backoff, 2.0, 0.0, 1, 513); gpr_timespec now = gpr_time_0(GPR_TIMESPAN); gpr_timespec next = gpr_backoff_begin(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(3, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(7, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(15, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(31, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(63, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(127, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(255, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(511, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1023, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(1536, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2049, GPR_TIMESPAN), next) == 0); now = next; next = gpr_backoff_step(&backoff, now); GPR_ASSERT(gpr_time_cmp(gpr_time_from_millis(2562, GPR_TIMESPAN), next) == 0); }
static gpr_timespec n_millis_time(int n) { return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(n, GPR_TIMESPAN)); }
static void add_test(void) { gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME); int i; grpc_timer timers[20]; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_timer_list_init(start); memset(cb_called, 0, sizeof(cb_called)); /* 10 ms timers. will expire in the current epoch */ for (i = 0; i < 10; i++) { grpc_timer_init(&exec_ctx, &timers[i], gpr_time_add(start, gpr_time_from_millis(10, GPR_TIMESPAN)), cb, (void *)(intptr_t)i, start); } /* 1010 ms timers. will expire in the next epoch */ for (i = 10; i < 20; i++) { grpc_timer_init( &exec_ctx, &timers[i], gpr_time_add(start, gpr_time_from_millis(1010, GPR_TIMESPAN)), cb, (void *)(intptr_t)i, start); } /* collect timers. Only the first batch should be ready. */ GPR_ASSERT(10 == grpc_timer_check(&exec_ctx, gpr_time_add(start, gpr_time_from_millis( 500, GPR_TIMESPAN)), NULL)); grpc_exec_ctx_finish(&exec_ctx); for (i = 0; i < 20; i++) { GPR_ASSERT(cb_called[i][1] == (i < 10)); GPR_ASSERT(cb_called[i][0] == 0); } GPR_ASSERT(0 == grpc_timer_check(&exec_ctx, gpr_time_add(start, gpr_time_from_millis( 600, GPR_TIMESPAN)), NULL)); grpc_exec_ctx_finish(&exec_ctx); for (i = 0; i < 30; i++) { GPR_ASSERT(cb_called[i][1] == (i < 10)); GPR_ASSERT(cb_called[i][0] == 0); } /* collect the rest of the timers */ GPR_ASSERT(10 == grpc_timer_check( &exec_ctx, gpr_time_add(start, gpr_time_from_millis( 1500, GPR_TIMESPAN)), NULL)); grpc_exec_ctx_finish(&exec_ctx); for (i = 0; i < 30; i++) { GPR_ASSERT(cb_called[i][1] == (i < 20)); GPR_ASSERT(cb_called[i][0] == 0); } GPR_ASSERT(0 == grpc_timer_check(&exec_ctx, gpr_time_add(start, gpr_time_from_millis( 1600, GPR_TIMESPAN)), NULL)); for (i = 0; i < 30; i++) { GPR_ASSERT(cb_called[i][1] == (i < 20)); GPR_ASSERT(cb_called[i][0] == 0); } grpc_timer_list_shutdown(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx); }
static gpr_timespec tfm(int m) { gpr_timespec t = gpr_time_from_millis(m, GPR_TIMESPAN); t.clock_type = GPR_CLOCK_REALTIME; return t; }
gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) { backoff->current_timeout_millis = backoff->min_timeout_millis; return gpr_time_add( now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN)); }
void grpc_iomgr_shutdown(void) { grpc_iomgr_closure *closure; gpr_timespec shutdown_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME); gpr_mu_lock(&g_mu); g_shutdown = 1; while (g_cbs_head != NULL || g_root_object.next != &g_root_object) { if (gpr_time_cmp( gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time), gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) { if (g_cbs_head != NULL && g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed and executing " "final callbacks", count_objects()); } else if (g_cbs_head != NULL) { gpr_log(GPR_DEBUG, "Executing final iomgr callbacks"); } else { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed", count_objects()); } last_warning_time = gpr_now(GPR_CLOCK_REALTIME); } if (g_cbs_head) { do { closure = g_cbs_head; g_cbs_head = closure->next; if (!g_cbs_head) g_cbs_tail = NULL; gpr_mu_unlock(&g_mu); closure->cb(closure->cb_arg, 0); gpr_mu_lock(&g_mu); } while (g_cbs_head); continue; } if (grpc_alarm_check(&g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL)) { continue; } if (g_root_object.next != &g_root_object) { int timeout = 0; while (g_cbs_head == NULL) { gpr_timespec short_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) { if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { timeout = 1; break; } } } if (timeout) { gpr_log(GPR_DEBUG, "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); dump_objects("LEAKED"); break; } } } gpr_mu_unlock(&g_mu); grpc_kick_poller(); gpr_event_wait(&g_background_callback_executor_done, gpr_inf_future(GPR_CLOCK_REALTIME)); grpc_alarm_list_shutdown(); grpc_iomgr_platform_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); }
void grpc_iomgr_shutdown(void) { gpr_timespec shutdown_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_iomgr_platform_flush(); gpr_mu_lock(&g_mu); g_shutdown = 1; while (g_root_object.next != &g_root_object) { if (gpr_time_cmp( gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time), gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) { if (g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed", count_objects()); } last_warning_time = gpr_now(GPR_CLOCK_REALTIME); } if (grpc_timer_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL)) { gpr_mu_unlock(&g_mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(&g_mu); continue; } if (g_root_object.next != &g_root_object) { gpr_timespec short_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) { if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { if (g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); dump_objects("LEAKED"); if (grpc_iomgr_abort_on_leaks()) { abort(); } } break; } } } } gpr_mu_unlock(&g_mu); grpc_timer_list_shutdown(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx); /* ensure all threads have left g_mu */ gpr_mu_lock(&g_mu); gpr_mu_unlock(&g_mu); grpc_pollset_global_shutdown(); grpc_iomgr_platform_shutdown(); grpc_exec_ctx_global_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); }
gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) { backoff->current_timeout_millis = backoff->initial_connect_timeout; const int64_t first_timeout = GPR_MAX(backoff->current_timeout_millis, backoff->min_timeout_millis); return gpr_time_add(now, gpr_time_from_millis(first_timeout, GPR_TIMESPAN)); }
gpr_timespec grpc_timeout_seconds_to_deadline(int64_t time_s) { return gpr_time_add( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(grpc_test_slowdown_factor() * (int64_t)1e3 * time_s, GPR_TIMESPAN)); }