static void shutdown_server(h2o_socket_t *listener, const char *err)
{
	if (err)
		ERROR(err);
	else {
		thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t,
		                                                      event_loop,
		                                                      listener->data);

		ctx->global_data->shutdown = true;

		// Close the listening sockets immediately, so that if another instance
		// of the application is started before the current one exits (e.g. when
		// doing an update), it will accept all incoming connections.
		if (ctx->event_loop.h2o_https_socket) {
			h2o_socket_read_stop(ctx->event_loop.h2o_https_socket);
			h2o_socket_close(ctx->event_loop.h2o_https_socket);
			ctx->event_loop.h2o_https_socket = NULL;
		}

		if (ctx->event_loop.h2o_socket) {
			h2o_socket_read_stop(ctx->event_loop.h2o_socket);
			h2o_socket_close(ctx->event_loop.h2o_socket);
			ctx->event_loop.h2o_socket = NULL;
		}

		for (size_t i = ctx->config->thread_num - 1; i > 0; i--)
			h2o_multithread_send_message(&ctx->global_thread_data[i].h2o_receiver, NULL);
	}
}
Exemple #2
0
static void discard_req(h2o_memcached_req_t *req)
{
    switch (req->type) {
    case REQ_TYPE_GET:
        h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
        break;
    default:
        free_req(req);
        break;
    }
}
static void shutdown_server(h2o_socket_t *listener, const char *err)
{
	if (!err) {
		thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t,
		                                                      event_loop,
		                                                      listener->data);

		ctx->global_data->shutdown = true;
		h2o_socket_read_stop(ctx->event_loop.h2o_socket);

		for (size_t i = 1; i < ctx->global_data->config->thread_num; i++)
			h2o_multithread_send_message(&ctx[i].event_loop.h2o_receiver, NULL);
	}
}
Exemple #4
0
static void lookup_and_respond(h2o_hostinfo_getaddr_req_t *req)
{
    struct addrinfo *res;

    int ret = getaddrinfo(req->_in.name, req->_in.serv, &req->_in.hints, &res);
    req->_out.message = (h2o_multithread_message_t){0};
    if (ret != 0) {
        req->_out.errstr = gai_strerror(ret);
        req->_out.ai = NULL;
    } else {
        req->_out.errstr = NULL;
        req->_out.ai = res;
    }

    h2o_multithread_send_message(req->_receiver, &req->_out.message);
}
Exemple #5
0
static void send_empty_message(h2o_multithread_receiver_t *receiver)
{
    h2o_multithread_message_t *message = h2o_mem_alloc(sizeof(*message));
    *message = (h2o_multithread_message_t){{NULL}};
    h2o_multithread_send_message(receiver, message);
}
Exemple #6
0
static void reader_main(h2o_memcached_context_t *ctx)
{
    struct st_h2o_memcached_conn_t conn = {ctx, {}, PTHREAD_MUTEX_INITIALIZER, {&conn.inflight, &conn.inflight}, 0};
    pthread_t writer_thread;
    yrmcds_response resp;
    yrmcds_error err;

    /* connect to server and start the writer thread */
    connect_to_server(conn.ctx, &conn.yrmcds);
    pthread_create(&writer_thread, NULL, writer_main, &conn);

    pthread_mutex_lock(&conn.ctx->mutex);
    ++conn.ctx->num_threads_connected;
    pthread_mutex_unlock(&conn.ctx->mutex);

    /* receive data until an error occurs */
    while (1) {
        if ((err = yrmcds_recv(&conn.yrmcds, &resp)) != YRMCDS_OK) {
            fprintf(stderr, "[lib/common/memcached.c] yrmcds_recv:%s\n", yrmcds_strerror(err));
            break;
        }
        h2o_memcached_req_t *req = pop_inflight(&conn, resp.serial);
        if (req == NULL) {
            fprintf(stderr, "[lib/common/memcached.c] received unexpected serial\n");
            break;
        }
        if (resp.status == YRMCDS_STATUS_OK) {
            req->data.get.value = h2o_iovec_init(h2o_mem_alloc(resp.data_len), resp.data_len);
            memcpy(req->data.get.value.base, resp.data, resp.data_len);
            h2o_mem_set_secure((void *)resp.data, 0, resp.data_len);
        }
        h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
    }

    /* send error to all the reqs in-flight */
    pthread_mutex_lock(&conn.mutex);
    while (!h2o_linklist_is_empty(&conn.inflight)) {
        h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, inflight, conn.inflight.next);
        h2o_linklist_unlink(&req->inflight);
        assert(req->type == REQ_TYPE_GET);
        h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
    }
    pthread_mutex_unlock(&conn.mutex);

    /* stop the writer thread */
    __sync_add_and_fetch(&conn.writer_exit_requested, 1);
    pthread_mutex_lock(&conn.ctx->mutex);
    pthread_cond_broadcast(&conn.ctx->cond);
    pthread_mutex_unlock(&conn.ctx->mutex);
    pthread_join(writer_thread, NULL);

    /* decrement num_threads_connected, and discard all the pending requests if no connections are alive */
    pthread_mutex_lock(&conn.ctx->mutex);
    if (--conn.ctx->num_threads_connected == 0) {
        while (!h2o_linklist_is_empty(&conn.ctx->pending)) {
            h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, pending, conn.ctx->pending.next);
            h2o_linklist_unlink(&req->pending);
            discard_req(req);
        }
    }
    pthread_mutex_unlock(&conn.ctx->mutex);

    /* close the connection */
    yrmcds_close(&conn.yrmcds);
}