From 488355b9c1b0fd6ea1faa2db3efe4af2b712ecd1 Mon Sep 17 00:00:00 2001 From: cho45 Date: Mon, 30 Jul 2018 15:01:50 +0900 Subject: [PATCH 1/4] add failing test --- t/50status.t | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/t/50status.t b/t/50status.t index bca12f83cb..961a9d4cd3 100644 --- a/t/50status.t +++ b/t/50status.t @@ -84,6 +84,33 @@ EOT }; +subtest "json internal request bug (duplication of durations and events)" => sub { + my $server = spawn_h2o(sub { + my ($port, $tls_port) = @_; + << "EOT"; +duration-stats: ON +hosts: + default: + paths: + /server-status: + status: ON + /server-status2: + status: ON +EOT + }); + + { + my $resp = `curl --silent -o /dev/stderr 'http://127.0.0.1:$server->{port}/server-status/json?show=durations,events,main' 2>&1 > /dev/null`; + is scalar @{[ $resp =~ m!"status-errors.400":!g ]}, 1, "only once"; + is scalar @{[ $resp =~ m!"connect-time-0":!g ]}, 1, "only once"; + } + + { + my $resp = `curl --silent -o /dev/stderr 'http://127.0.0.1:$server->{port}/server-status2/json?show=durations,events,main' 2>&1 > /dev/null`; + is scalar @{[ $resp =~ m!"status-errors.400":!g ]}, 1, "only once"; + is scalar @{[ $resp =~ m!"connect-time-0":!g ]}, 1, "only once"; + } +}; done_testing(); From 6a72fd7838380842d5c493537481be13285cb5c1 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 30 Jul 2018 15:47:29 +0900 Subject: [PATCH 2/4] use const pointers to represent the status handlers --- include/h2o.h | 9 ++++----- lib/core/config.c | 13 +------------ lib/handler/status.c | 12 ++++++------ lib/handler/status/durations.c | 2 +- lib/handler/status/events.c | 2 +- lib/handler/status/requests.c | 2 +- src/main.c | 3 ++- 7 files changed, 16 insertions(+), 27 deletions(-) diff --git a/include/h2o.h b/include/h2o.h index d8c697dc44..a3cf257392 100644 --- a/include/h2o.h +++ b/include/h2o.h @@ -319,14 +319,14 @@ typedef struct st_h2o_protocol_callbacks_t { } h2o_protocol_callbacks_t; typedef h2o_iovec_t (*final_status_handler_cb)(void *ctx, h2o_globalconf_t *gconf, h2o_req_t *req); -typedef struct st_h2o_status_handler_t { +typedef const struct st_h2o_status_handler_t { h2o_iovec_t name; + h2o_iovec_t (* final)(void *ctx, h2o_globalconf_t *gconf, h2o_req_t *req); /* mandatory, will be passed the optional context */ void *(*init)(void); /* optional callback, allocates a context that will be passed to per_thread() */ void (*per_thread)(void *priv, h2o_context_t *ctx); /* optional callback, will be called for each thread */ - h2o_iovec_t (* final)(void *ctx, h2o_globalconf_t *gconf, h2o_req_t *req); /* mandatory, will be passed the optional context */ } h2o_status_handler_t; -typedef H2O_VECTOR(h2o_status_handler_t) h2o_status_callbacks_t; +typedef H2O_VECTOR(h2o_status_handler_t *) h2o_status_callbacks_t; typedef enum h2o_send_informational_mode { H2O_SEND_INFORMATIONAL_MODE_EXCEPT_H1, @@ -1514,8 +1514,7 @@ h2o_pathconf_t *h2o_config_register_path(h2o_hostconf_t *hostconf, const char *p /** * registers an extra status handler */ -void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t); -void h2o_config_register_simple_status_handler(h2o_globalconf_t *config, h2o_iovec_t name, final_status_handler_cb status_handler); +void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t *status_handler); /** * disposes of the resources allocated for the global configuration */ diff --git a/lib/core/config.c b/lib/core/config.c index 2bd2762d6b..1347c82d8c 100644 --- a/lib/core/config.c +++ b/lib/core/config.c @@ -213,23 +213,12 @@ h2o_pathconf_t *h2o_config_register_path(h2o_hostconf_t *hostconf, const char *p return pathconf; } -void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t status_handler) +void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t *status_handler) { h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1); config->statuses.entries[config->statuses.size++] = status_handler; } -void h2o_config_register_simple_status_handler(h2o_globalconf_t *config, h2o_iovec_t name, final_status_handler_cb status_handler) -{ - h2o_status_handler_t *sh; - - h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1); - sh = &config->statuses.entries[config->statuses.size++]; - memset(sh, 0, sizeof(*sh)); - sh->name = h2o_strdup(NULL, name.base, name.len); - sh->final = status_handler; -} - h2o_hostconf_t *h2o_config_register_host(h2o_globalconf_t *config, h2o_iovec_t host, uint16_t port) { h2o_hostconf_t *hostconf = NULL; diff --git a/lib/handler/status.c b/lib/handler/status.c index 93befed3bd..1880f959a7 100644 --- a/lib/handler/status.c +++ b/lib/handler/status.c @@ -63,7 +63,7 @@ static void collect_reqs_of_context(struct st_h2o_status_collector_t *collector, for (i = 0; i < ctx->globalconf->statuses.size; i++) { struct st_status_ctx_t *sc = collector->status_ctx.entries + i; - h2o_status_handler_t *sh = ctx->globalconf->statuses.entries + i; + h2o_status_handler_t *sh = ctx->globalconf->statuses.entries[i]; if (sc->active && sh->per_thread != NULL) sh->per_thread(sc->ctx, ctx); } @@ -99,7 +99,7 @@ static void send_response(struct st_h2o_status_collector_t *collector) int coma_removed = 0; for (i = 0; i < req->conn->ctx->globalconf->statuses.size; i++) { - h2o_status_handler_t *sh = &req->conn->ctx->globalconf->statuses.entries[i]; + h2o_status_handler_t *sh = req->conn->ctx->globalconf->statuses.entries[i]; if (!collector->status_ctx.entries[i].active) { continue; } @@ -162,7 +162,7 @@ static int on_req_json(struct st_h2o_root_status_handler_t *self, h2o_req_t *req h2o_status_handler_t *sh; h2o_vector_reserve(&req->pool, &collector->status_ctx, collector->status_ctx.size + 1); - sh = &req->conn->ctx->globalconf->statuses.entries[i]; + sh = req->conn->ctx->globalconf->statuses.entries[i]; if (status_list.base) { if (!h2o_contains_token(status_list.base, status_list.len, sh->name.base, sh->name.len, ',')) { @@ -264,7 +264,7 @@ void h2o_status_register(h2o_pathconf_t *conf) self->super.on_context_init = on_context_init; self->super.on_context_dispose = on_context_dispose; self->super.on_req = on_req; - h2o_config_register_status_handler(conf->global, requests_status_handler); - h2o_config_register_status_handler(conf->global, events_status_handler); - h2o_config_register_status_handler(conf->global, durations_status_handler); + h2o_config_register_status_handler(conf->global, &requests_status_handler); + h2o_config_register_status_handler(conf->global, &events_status_handler); + h2o_config_register_status_handler(conf->global, &durations_status_handler); } diff --git a/lib/handler/status/durations.c b/lib/handler/status/durations.c index b37e0c6650..7537f1232e 100644 --- a/lib/handler/status/durations.c +++ b/lib/handler/status/durations.c @@ -204,5 +204,5 @@ void h2o_duration_stats_register(h2o_globalconf_t *conf) } h2o_status_handler_t durations_status_handler = { - {H2O_STRLIT("durations")}, durations_status_init, durations_status_per_thread, durations_status_final, + {H2O_STRLIT("durations")}, durations_status_final, durations_status_init, durations_status_per_thread }; diff --git a/lib/handler/status/events.c b/lib/handler/status/events.c index 178125e70c..d5e1533e4b 100644 --- a/lib/handler/status/events.c +++ b/lib/handler/status/events.c @@ -108,5 +108,5 @@ static h2o_iovec_t events_status_final(void *priv, h2o_globalconf_t *gconf, h2o_ } h2o_status_handler_t events_status_handler = { - {H2O_STRLIT("events")}, events_status_init, events_status_per_thread, events_status_final, + {H2O_STRLIT("events")}, events_status_final, events_status_init, events_status_per_thread }; diff --git a/lib/handler/status/requests.c b/lib/handler/status/requests.c index 4854e4a1f6..b1c5c96c6e 100644 --- a/lib/handler/status/requests.c +++ b/lib/handler/status/requests.c @@ -147,5 +147,5 @@ static h2o_iovec_t requests_status_final(void *priv, h2o_globalconf_t *gconf, h2 } h2o_status_handler_t requests_status_handler = { - {H2O_STRLIT("requests")}, requests_status_init, requests_status_per_thread, requests_status_final, + {H2O_STRLIT("requests")}, requests_status_final, requests_status_init, requests_status_per_thread }; diff --git a/src/main.c b/src/main.c index fea5d38f0b..1cf7b76a97 100644 --- a/src/main.c +++ b/src/main.c @@ -1948,7 +1948,8 @@ static void setup_configurators(void) h2o_mruby_register_configurator(&conf.globalconf); #endif - h2o_config_register_simple_status_handler(&conf.globalconf, (h2o_iovec_t){H2O_STRLIT("main")}, on_extra_status); + static h2o_status_handler_t extra_status_handler = {{H2O_STRLIT("main")}, on_extra_status}; + h2o_config_register_status_handler(&conf.globalconf, &extra_status_handler); } int main(int argc, char **argv) From 93d8ed3d85b24ddcf7021c832bace32cefd75875 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 30 Jul 2018 15:49:23 +0900 Subject: [PATCH 3/4] register if not yet being done --- lib/core/config.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/core/config.c b/lib/core/config.c index 1347c82d8c..c027d9b835 100644 --- a/lib/core/config.c +++ b/lib/core/config.c @@ -215,6 +215,12 @@ h2o_pathconf_t *h2o_config_register_path(h2o_hostconf_t *hostconf, const char *p void h2o_config_register_status_handler(h2o_globalconf_t *config, h2o_status_handler_t *status_handler) { + /* check if the status handler is already registered */ + size_t i; + for (i = 0; i != config->statuses.size; ++i) + if (config->statuses.entries[i] == status_handler) + return; + /* register the new handler */ h2o_vector_reserve(NULL, &config->statuses, config->statuses.size + 1); config->statuses.entries[config->statuses.size++] = status_handler; } From 074af46b009f679c9013c29980ab262005a83ce5 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 30 Jul 2018 15:51:25 +0900 Subject: [PATCH 4/4] to avoid name conflicts in link-phase, extern variables must have the "h2o_" prefix --- lib/handler/status.c | 12 ++++++------ lib/handler/status/durations.c | 2 +- lib/handler/status/events.c | 2 +- lib/handler/status/requests.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/handler/status.c b/lib/handler/status.c index 1880f959a7..906f20de81 100644 --- a/lib/handler/status.c +++ b/lib/handler/status.c @@ -21,9 +21,9 @@ */ #include "h2o.h" -extern h2o_status_handler_t events_status_handler; -extern h2o_status_handler_t requests_status_handler; -extern h2o_status_handler_t durations_status_handler; +extern h2o_status_handler_t h2o_events_status_handler; +extern h2o_status_handler_t h2o_requests_status_handler; +extern h2o_status_handler_t h2o_durations_status_handler; struct st_h2o_status_logger_t { h2o_logger_t super; @@ -264,7 +264,7 @@ void h2o_status_register(h2o_pathconf_t *conf) self->super.on_context_init = on_context_init; self->super.on_context_dispose = on_context_dispose; self->super.on_req = on_req; - h2o_config_register_status_handler(conf->global, &requests_status_handler); - h2o_config_register_status_handler(conf->global, &events_status_handler); - h2o_config_register_status_handler(conf->global, &durations_status_handler); + h2o_config_register_status_handler(conf->global, &h2o_requests_status_handler); + h2o_config_register_status_handler(conf->global, &h2o_events_status_handler); + h2o_config_register_status_handler(conf->global, &h2o_durations_status_handler); } diff --git a/lib/handler/status/durations.c b/lib/handler/status/durations.c index 7537f1232e..687048ffd3 100644 --- a/lib/handler/status/durations.c +++ b/lib/handler/status/durations.c @@ -203,6 +203,6 @@ void h2o_duration_stats_register(h2o_globalconf_t *conf) } } -h2o_status_handler_t durations_status_handler = { +h2o_status_handler_t h2o_durations_status_handler = { {H2O_STRLIT("durations")}, durations_status_final, durations_status_init, durations_status_per_thread }; diff --git a/lib/handler/status/events.c b/lib/handler/status/events.c index d5e1533e4b..0ae8827440 100644 --- a/lib/handler/status/events.c +++ b/lib/handler/status/events.c @@ -107,6 +107,6 @@ static h2o_iovec_t events_status_final(void *priv, h2o_globalconf_t *gconf, h2o_ #undef H2_AGG_ERR } -h2o_status_handler_t events_status_handler = { +h2o_status_handler_t h2o_events_status_handler = { {H2O_STRLIT("events")}, events_status_final, events_status_init, events_status_per_thread }; diff --git a/lib/handler/status/requests.c b/lib/handler/status/requests.c index b1c5c96c6e..2045f4315b 100644 --- a/lib/handler/status/requests.c +++ b/lib/handler/status/requests.c @@ -146,6 +146,6 @@ static h2o_iovec_t requests_status_final(void *priv, h2o_globalconf_t *gconf, h2 return ret; } -h2o_status_handler_t requests_status_handler = { +h2o_status_handler_t h2o_requests_status_handler = { {H2O_STRLIT("requests")}, requests_status_final, requests_status_init, requests_status_per_thread };