Merge branch 'ds/trace2-tolerate-failed-timestamp' into seen
Functions like `xstrfmt()` and `xcalloc()` have been banned from use in the trace2 API codebase to prevent calls to `die()` which lead to unwanted process exits and recursion when memory allocation fails. * ds/trace2-tolerate-failed-timestamp: trace2: remove use of xcalloc() trace2: remove use of ALLOC_GROW() trace2: remove use of xstrfmt() trace2: remove use of ALLOC_ARRAY() trace2: remove use of xstrdup() trace2: tolerate failed timestamp formatting banned-die: create header for banning of functionsseen
commit
075cd7bce4
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef BANNED_DIE_H
|
||||||
|
#define BANNED_DIE_H
|
||||||
|
|
||||||
|
#include "banned.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This header lists functions that must not be used by low-level APIs
|
||||||
|
* because they can cause Git to terminate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef die
|
||||||
|
#define die BANNED(die)
|
||||||
|
|
||||||
|
#undef xsnprintf
|
||||||
|
#define xsnprintf(...) BANNED(xsnprintf)
|
||||||
|
|
||||||
|
#undef xstrdup
|
||||||
|
#define xstrdup(str) BANNED(xstrdup)
|
||||||
|
|
||||||
|
#undef xcalloc
|
||||||
|
#define xcalloc(nmemb, size) BANNED(xcalloc)
|
||||||
|
|
||||||
|
#undef xstrfmt
|
||||||
|
#define xstrfmt(...) BANNED(xstrfmt)
|
||||||
|
|
||||||
|
#undef ALLOC_ARRAY
|
||||||
|
#define ALLOC_ARRAY(x, alloc) BANNED(ALLOC_ARRAY)
|
||||||
|
|
||||||
|
#undef ALLOC_GROW
|
||||||
|
#define ALLOC_GROW(x, nr, alloc) BANNED(ALLOC_GROW)
|
||||||
|
|
||||||
|
#endif /* BANNED_DIE_H */
|
||||||
|
|
@ -332,7 +332,8 @@ test_expect_success 'unsafe URLs are redacted by default in cmd_start events' '
|
||||||
|
|
||||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||||
test-tool trace2 300redact_start git clone https://user:pwd@example.com/ clone2 &&
|
test-tool trace2 300redact_start git clone https://user:pwd@example.com/ clone2 &&
|
||||||
test_grep ! user:pwd trace.event
|
test_grep ! user:pwd trace.event &&
|
||||||
|
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'unsafe URLs are redacted by default in child_start events' '
|
test_expect_success 'unsafe URLs are redacted by default in child_start events' '
|
||||||
|
|
@ -341,7 +342,8 @@ test_expect_success 'unsafe URLs are redacted by default in child_start events'
|
||||||
|
|
||||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||||
test-tool trace2 301redact_child_start git clone https://user:pwd@example.com/ clone2 &&
|
test-tool trace2 301redact_child_start git clone https://user:pwd@example.com/ clone2 &&
|
||||||
test_grep ! user:pwd trace.event
|
test_grep ! user:pwd trace.event &&
|
||||||
|
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'unsafe URLs are redacted by default in exec events' '
|
test_expect_success 'unsafe URLs are redacted by default in exec events' '
|
||||||
|
|
@ -350,7 +352,8 @@ test_expect_success 'unsafe URLs are redacted by default in exec events' '
|
||||||
|
|
||||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||||
test-tool trace2 302redact_exec git clone https://user:pwd@example.com/ clone2 &&
|
test-tool trace2 302redact_exec git clone https://user:pwd@example.com/ clone2 &&
|
||||||
test_grep ! user:pwd trace.event
|
test_grep ! user:pwd trace.event &&
|
||||||
|
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'unsafe URLs are redacted by default in def_param events' '
|
test_expect_success 'unsafe URLs are redacted by default in def_param events' '
|
||||||
|
|
@ -359,7 +362,8 @@ test_expect_success 'unsafe URLs are redacted by default in def_param events' '
|
||||||
|
|
||||||
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
GIT_TRACE2_EVENT="$(pwd)/trace.event" \
|
||||||
test-tool trace2 303redact_def_param url https://user:pwd@example.com/ &&
|
test-tool trace2 303redact_def_param url https://user:pwd@example.com/ &&
|
||||||
test_grep ! user:pwd trace.event
|
test_grep ! user:pwd trace.event &&
|
||||||
|
test_grep "user:<REDACTED>@example.com/" trace.event
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
||||||
52
trace2.c
52
trace2.c
|
|
@ -17,6 +17,8 @@
|
||||||
#include "trace2/tr2_tgt.h"
|
#include "trace2/tr2_tgt.h"
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
#include "trace2/tr2_tmr.h"
|
#include "trace2/tr2_tmr.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
static int trace2_enabled;
|
static int trace2_enabled;
|
||||||
static int trace2_redact = 1;
|
static int trace2_redact = 1;
|
||||||
|
|
@ -259,7 +261,10 @@ int trace2_is_enabled(void)
|
||||||
static const char *redact_arg(const char *arg)
|
static const char *redact_arg(const char *arg)
|
||||||
{
|
{
|
||||||
const char *p, *colon;
|
const char *p, *colon;
|
||||||
|
const char *redact = ":<REDACTED>";
|
||||||
|
char *redacted;
|
||||||
size_t at;
|
size_t at;
|
||||||
|
size_t prefix_len, suffix_len, redacted_len, redact_len;
|
||||||
|
|
||||||
if (!trace2_redact ||
|
if (!trace2_redact ||
|
||||||
(!skip_prefix(arg, "https://", &p) &&
|
(!skip_prefix(arg, "https://", &p) &&
|
||||||
|
|
@ -274,7 +279,25 @@ static const char *redact_arg(const char *arg)
|
||||||
if (!colon)
|
if (!colon)
|
||||||
return arg;
|
return arg;
|
||||||
|
|
||||||
return xstrfmt("%.*s:<REDACTED>%s", (int)(colon - arg), arg, p + at);
|
redact_len = strlen(redact);
|
||||||
|
prefix_len = colon - arg;
|
||||||
|
suffix_len = strlen(p + at);
|
||||||
|
|
||||||
|
if (unsigned_add_overflows(prefix_len, suffix_len) ||
|
||||||
|
unsigned_add_overflows(prefix_len + suffix_len, redact_len) ||
|
||||||
|
unsigned_add_overflows(prefix_len + suffix_len + redact_len, 1))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
redacted_len = prefix_len + suffix_len + redact_len + 1;
|
||||||
|
|
||||||
|
redacted = malloc(redacted_len);
|
||||||
|
if (!redacted)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memcpy(redacted, arg, prefix_len);
|
||||||
|
memcpy(redacted + prefix_len, redact, redact_len);
|
||||||
|
memcpy(redacted + prefix_len + redact_len, p + at, suffix_len + 1);
|
||||||
|
return redacted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -299,11 +322,17 @@ static const char **redact_argv(const char **argv)
|
||||||
|
|
||||||
if (!argv[i])
|
if (!argv[i])
|
||||||
return argv;
|
return argv;
|
||||||
|
if (!redacted)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (j = 0; argv[j]; j++)
|
for (j = 0; argv[j]; j++)
|
||||||
; /* keep counting */
|
; /* keep counting */
|
||||||
|
|
||||||
ALLOC_ARRAY(ret, j + 1);
|
ret = calloc(j + 1, sizeof(*ret));
|
||||||
|
if (!ret) {
|
||||||
|
free((char *)redacted);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
ret[j] = NULL;
|
ret[j] = NULL;
|
||||||
|
|
||||||
for (j = 0; j < i; j++)
|
for (j = 0; j < i; j++)
|
||||||
|
|
@ -311,7 +340,14 @@ static const char **redact_argv(const char **argv)
|
||||||
ret[i] = redacted;
|
ret[i] = redacted;
|
||||||
for (++i; argv[i]; i++) {
|
for (++i; argv[i]; i++) {
|
||||||
redacted = redact_arg(argv[i]);
|
redacted = redact_arg(argv[i]);
|
||||||
ret[i] = redacted ? redacted : argv[i];
|
if (!redacted) {
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
if (ret[j] != argv[j])
|
||||||
|
free((void *)ret[j]);
|
||||||
|
free(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret[i] = redacted;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -344,6 +380,8 @@ void trace2_cmd_start_fl(const char *file, int line, const char **argv)
|
||||||
us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
|
us_elapsed_absolute = tr2tls_absolute_elapsed(us_now);
|
||||||
|
|
||||||
redacted = redact_argv(argv);
|
redacted = redact_argv(argv);
|
||||||
|
if (!redacted)
|
||||||
|
return;
|
||||||
|
|
||||||
for_each_wanted_builtin (j, tgt_j)
|
for_each_wanted_builtin (j, tgt_j)
|
||||||
if (tgt_j->pfn_start_fl)
|
if (tgt_j->pfn_start_fl)
|
||||||
|
|
@ -512,6 +550,7 @@ void trace2_child_start_fl(const char *file, int line,
|
||||||
uint64_t us_now;
|
uint64_t us_now;
|
||||||
uint64_t us_elapsed_absolute;
|
uint64_t us_elapsed_absolute;
|
||||||
const char **orig_argv = cmd->args.v;
|
const char **orig_argv = cmd->args.v;
|
||||||
|
const char **redacted;
|
||||||
|
|
||||||
if (!trace2_enabled)
|
if (!trace2_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
@ -529,7 +568,10 @@ void trace2_child_start_fl(const char *file, int line,
|
||||||
* temporarily replace the original argv (inside the `strvec`)
|
* temporarily replace the original argv (inside the `strvec`)
|
||||||
* with a possibly redacted version.
|
* with a possibly redacted version.
|
||||||
*/
|
*/
|
||||||
cmd->args.v = redact_argv(orig_argv);
|
redacted = redact_argv(orig_argv);
|
||||||
|
if (!redacted)
|
||||||
|
return;
|
||||||
|
cmd->args.v = redacted;
|
||||||
|
|
||||||
for_each_wanted_builtin (j, tgt_j)
|
for_each_wanted_builtin (j, tgt_j)
|
||||||
if (tgt_j->pfn_child_start_fl)
|
if (tgt_j->pfn_child_start_fl)
|
||||||
|
|
@ -621,6 +663,8 @@ int trace2_exec_fl(const char *file, int line, const char *exe,
|
||||||
exec_id = tr2tls_locked_increment(&tr2_next_exec_id);
|
exec_id = tr2tls_locked_increment(&tr2_next_exec_id);
|
||||||
|
|
||||||
redacted = redact_argv(argv);
|
redacted = redact_argv(argv);
|
||||||
|
if (!redacted)
|
||||||
|
return exec_id;
|
||||||
|
|
||||||
for_each_wanted_builtin (j, tgt_j)
|
for_each_wanted_builtin (j, tgt_j)
|
||||||
if (tgt_j->pfn_exec_fl)
|
if (tgt_j->pfn_exec_fl)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
#include "trace2/tr2_cfg.h"
|
#include "trace2/tr2_cfg.h"
|
||||||
#include "trace2/tr2_sysenv.h"
|
#include "trace2/tr2_sysenv.h"
|
||||||
#include "wildmatch.h"
|
#include "wildmatch.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
static struct string_list tr2_cfg_patterns = STRING_LIST_INIT_DUP;
|
static struct string_list tr2_cfg_patterns = STRING_LIST_INIT_DUP;
|
||||||
static int tr2_cfg_loaded;
|
static int tr2_cfg_loaded;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "trace2/tr2_cmd_name.h"
|
#include "trace2/tr2_cmd_name.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
#define TR2_ENVVAR_PARENT_NAME "GIT_TRACE2_PARENT_NAME"
|
#define TR2_ENVVAR_PARENT_NAME "GIT_TRACE2_PARENT_NAME"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
#include "trace2/tr2_tgt.h"
|
#include "trace2/tr2_tgt.h"
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
#include "trace2/tr2_ctr.h"
|
#include "trace2/tr2_ctr.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A global counter block to aggregate values from the partial sums
|
* A global counter block to aggregate values from the partial sums
|
||||||
|
|
@ -53,7 +55,11 @@ static struct tr2_counter_metadata tr2_counter_metadata[TRACE2_NUMBER_OF_COUNTER
|
||||||
void tr2_counter_increment(enum trace2_counter_id cid, uint64_t value)
|
void tr2_counter_increment(enum trace2_counter_id cid, uint64_t value)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
struct tr2_counter *c = &ctx->counter_block.counter[cid];
|
struct tr2_counter *c;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
c = &ctx->counter_block.counter[cid];
|
||||||
|
|
||||||
c->value += value;
|
c->value += value;
|
||||||
|
|
||||||
|
|
@ -67,6 +73,8 @@ void tr2_update_final_counters(void)
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
enum trace2_counter_id cid;
|
enum trace2_counter_id cid;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
if (!ctx->used_any_counter)
|
if (!ctx->used_any_counter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -88,6 +96,8 @@ void tr2_emit_per_thread_counters(tr2_tgt_evt_counter_t *fn_apply)
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
enum trace2_counter_id cid;
|
enum trace2_counter_id cid;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
if (!ctx->used_any_per_thread_counter)
|
if (!ctx->used_any_per_thread_counter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
#include "trace2/tr2_dst.h"
|
#include "trace2/tr2_dst.h"
|
||||||
#include "trace2/tr2_sid.h"
|
#include "trace2/tr2_sid.h"
|
||||||
#include "trace2/tr2_sysenv.h"
|
#include "trace2/tr2_sysenv.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How many attempts we will make at creating an automatically-named trace file.
|
* How many attempts we will make at creating an automatically-named trace file.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "trace2/tr2_tbuf.h"
|
#include "trace2/tr2_tbuf.h"
|
||||||
#include "trace2/tr2_sid.h"
|
#include "trace2/tr2_sid.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
#define TR2_ENVVAR_PARENT_SID "GIT_TRACE2_PARENT_SID"
|
#define TR2_ENVVAR_PARENT_SID "GIT_TRACE2_PARENT_SID"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "tr2_sysenv.h"
|
#include "tr2_sysenv.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each entry represents a trace2 setting.
|
* Each entry represents a trace2 setting.
|
||||||
|
|
@ -73,7 +75,9 @@ static int tr2_sysenv_cb(const char *key, const char *value,
|
||||||
if (!value)
|
if (!value)
|
||||||
return config_error_nonbool(key);
|
return config_error_nonbool(key);
|
||||||
free(tr2_sysenv_settings[k].value);
|
free(tr2_sysenv_settings[k].value);
|
||||||
tr2_sysenv_settings[k].value = xstrdup(value);
|
tr2_sysenv_settings[k].value = strdup(value);
|
||||||
|
if (!tr2_sysenv_settings[k].value)
|
||||||
|
return 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +113,7 @@ const char *tr2_sysenv_get(enum tr2_sysenv_variable var)
|
||||||
const char *v = getenv(tr2_sysenv_settings[var].env_var_name);
|
const char *v = getenv(tr2_sysenv_settings[var].env_var_name);
|
||||||
if (v && *v) {
|
if (v && *v) {
|
||||||
free(tr2_sysenv_settings[var].value);
|
free(tr2_sysenv_settings[var].value);
|
||||||
tr2_sysenv_settings[var].value = xstrdup(v);
|
tr2_sysenv_settings[var].value = strdup(v);
|
||||||
}
|
}
|
||||||
tr2_sysenv_settings[var].getenv_called = 1;
|
tr2_sysenv_settings[var].getenv_called = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,68 @@
|
||||||
#include "git-compat-util.h"
|
#include "git-compat-util.h"
|
||||||
#include "tr2_tbuf.h"
|
#include "tr2_tbuf.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
void tr2_tbuf_local_time(struct tr2_tbuf *tb)
|
void tr2_tbuf_local_time(struct tr2_tbuf *tb)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv = { 0 };
|
||||||
struct tm tm;
|
struct tm tm = { 0 };
|
||||||
time_t secs;
|
time_t secs;
|
||||||
|
int len;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
secs = tv.tv_sec;
|
secs = tv.tv_sec;
|
||||||
localtime_r(&secs, &tm);
|
localtime_r(&secs, &tm);
|
||||||
|
|
||||||
xsnprintf(tb->buf, sizeof(tb->buf), "%02d:%02d:%02d.%06ld", tm.tm_hour,
|
len = snprintf(tb->buf, sizeof(tb->buf), "%02d:%02d:%02d.%06ld",
|
||||||
tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||||
|
|
||||||
|
if (len < 0 || (size_t)len >= sizeof(tb->buf)) {
|
||||||
|
const char *blank = "00:00:00.000000";
|
||||||
|
strlcpy(tb->buf, blank, sizeof(tb->buf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tr2_tbuf_utc_datetime_extended(struct tr2_tbuf *tb)
|
void tr2_tbuf_utc_datetime_extended(struct tr2_tbuf *tb)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv = { 0 };
|
||||||
struct tm tm;
|
struct tm tm = { 0 };
|
||||||
time_t secs;
|
time_t secs;
|
||||||
|
int len;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
secs = tv.tv_sec;
|
secs = tv.tv_sec;
|
||||||
gmtime_r(&secs, &tm);
|
gmtime_r(&secs, &tm);
|
||||||
|
|
||||||
xsnprintf(tb->buf, sizeof(tb->buf),
|
len = snprintf(tb->buf, sizeof(tb->buf),
|
||||||
"%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ", tm.tm_year + 1900,
|
"%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ",
|
||||||
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
(long)tv.tv_usec);
|
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||||
|
|
||||||
|
if (len < 0 || (size_t)len >= sizeof(tb->buf)) {
|
||||||
|
const char *blank = "1900-00-00T00:00:00.000000Z";
|
||||||
|
strlcpy(tb->buf, blank, sizeof(tb->buf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tr2_tbuf_utc_datetime(struct tr2_tbuf *tb)
|
void tr2_tbuf_utc_datetime(struct tr2_tbuf *tb)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv = { 0 };
|
||||||
struct tm tm;
|
struct tm tm = { 0 };
|
||||||
time_t secs;
|
time_t secs;
|
||||||
|
int len;
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
secs = tv.tv_sec;
|
secs = tv.tv_sec;
|
||||||
gmtime_r(&secs, &tm);
|
gmtime_r(&secs, &tm);
|
||||||
|
|
||||||
xsnprintf(tb->buf, sizeof(tb->buf), "%4d%02d%02dT%02d%02d%02d.%06ldZ",
|
len = snprintf(tb->buf, sizeof(tb->buf),
|
||||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
|
"%4d%02d%02dT%02d%02d%02d.%06ldZ",
|
||||||
tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
|
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
|
||||||
|
|
||||||
|
if (len < 0 || (size_t)len >= sizeof(tb->buf)) {
|
||||||
|
const char *blank = "19000000T000000.000000Z";
|
||||||
|
strlcpy(tb->buf, blank, sizeof(tb->buf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@
|
||||||
#include "trace2/tr2_tgt.h"
|
#include "trace2/tr2_tgt.h"
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
#include "trace2/tr2_tmr.h"
|
#include "trace2/tr2_tmr.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
static struct tr2_dst tr2dst_event = {
|
static struct tr2_dst tr2dst_event = {
|
||||||
.sysenv_var = TR2_SYSENV_EVENT,
|
.sysenv_var = TR2_SYSENV_EVENT,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
#include "trace2/tr2_tgt.h"
|
#include "trace2/tr2_tgt.h"
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
#include "trace2/tr2_tmr.h"
|
#include "trace2/tr2_tmr.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
static struct tr2_dst tr2dst_normal = {
|
static struct tr2_dst tr2dst_normal = {
|
||||||
.sysenv_var = TR2_SYSENV_NORMAL,
|
.sysenv_var = TR2_SYSENV_NORMAL,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
#include "trace2/tr2_tgt.h"
|
#include "trace2/tr2_tgt.h"
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
#include "trace2/tr2_tmr.h"
|
#include "trace2/tr2_tmr.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
static struct tr2_dst tr2dst_perf = {
|
static struct tr2_dst tr2dst_perf = {
|
||||||
.sysenv_var = TR2_SYSENV_PERF,
|
.sysenv_var = TR2_SYSENV_PERF,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include "thread-utils.h"
|
#include "thread-utils.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize size of the thread stack for nested regions.
|
* Initialize size of the thread stack for nested regions.
|
||||||
|
|
@ -12,6 +14,9 @@
|
||||||
#define TR2_REGION_NESTING_INITIAL_SIZE (100)
|
#define TR2_REGION_NESTING_INITIAL_SIZE (100)
|
||||||
|
|
||||||
static struct tr2tls_thread_ctx *tr2tls_thread_main;
|
static struct tr2tls_thread_ctx *tr2tls_thread_main;
|
||||||
|
static struct tr2tls_thread_ctx tr2tls_thread_fallback = {
|
||||||
|
.thread_name = "unknown",
|
||||||
|
};
|
||||||
static uint64_t tr2tls_us_start_process;
|
static uint64_t tr2tls_us_start_process;
|
||||||
|
|
||||||
static pthread_mutex_t tr2tls_mutex;
|
static pthread_mutex_t tr2tls_mutex;
|
||||||
|
|
@ -36,16 +41,23 @@ void tr2tls_start_process_clock(void)
|
||||||
struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
||||||
uint64_t us_thread_start)
|
uint64_t us_thread_start)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = xcalloc(1, sizeof(*ctx));
|
struct tr2tls_thread_ctx *ctx = calloc(1, sizeof(*ctx));
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
|
if (!ctx)
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implicitly "tr2tls_push_self()" to capture the thread's start
|
* Implicitly "tr2tls_push_self()" to capture the thread's start
|
||||||
* time in array_us_start[0]. For the main thread this gives us the
|
* time in array_us_start[0]. For the main thread this gives us the
|
||||||
* application run time.
|
* application run time.
|
||||||
*/
|
*/
|
||||||
ctx->alloc = TR2_REGION_NESTING_INITIAL_SIZE;
|
ctx->alloc = TR2_REGION_NESTING_INITIAL_SIZE;
|
||||||
ctx->array_us_start = (uint64_t *)xcalloc(ctx->alloc, sizeof(uint64_t));
|
ctx->array_us_start = calloc(ctx->alloc, sizeof(uint64_t));
|
||||||
|
if (!ctx->array_us_start) {
|
||||||
|
free(ctx);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
ctx->array_us_start[ctx->nr_open_regions++] = us_thread_start;
|
ctx->array_us_start[ctx->nr_open_regions++] = us_thread_start;
|
||||||
|
|
||||||
ctx->thread_id = tr2tls_locked_increment(&tr2_next_thread_id);
|
ctx->thread_id = tr2tls_locked_increment(&tr2_next_thread_id);
|
||||||
|
|
@ -61,6 +73,10 @@ struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
||||||
pthread_setspecific(tr2tls_key, ctx);
|
pthread_setspecific(tr2tls_key, ctx);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
|
fallback:
|
||||||
|
pthread_setspecific(tr2tls_key, &tr2tls_thread_fallback);
|
||||||
|
return &tr2tls_thread_fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tr2tls_thread_ctx *tr2tls_get_self(void)
|
struct tr2tls_thread_ctx *tr2tls_get_self(void)
|
||||||
|
|
@ -83,6 +99,11 @@ struct tr2tls_thread_ctx *tr2tls_get_self(void)
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tr2tls_is_fallback(const struct tr2tls_thread_ctx *ctx)
|
||||||
|
{
|
||||||
|
return ctx == &tr2tls_thread_fallback;
|
||||||
|
}
|
||||||
|
|
||||||
int tr2tls_is_main_thread(void)
|
int tr2tls_is_main_thread(void)
|
||||||
{
|
{
|
||||||
if (!HAVE_THREADS)
|
if (!HAVE_THREADS)
|
||||||
|
|
@ -99,6 +120,9 @@ void tr2tls_unset_self(void)
|
||||||
|
|
||||||
pthread_setspecific(tr2tls_key, NULL);
|
pthread_setspecific(tr2tls_key, NULL);
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
free((char *)ctx->thread_name);
|
free((char *)ctx->thread_name);
|
||||||
free(ctx->array_us_start);
|
free(ctx->array_us_start);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
|
@ -107,8 +131,36 @@ void tr2tls_unset_self(void)
|
||||||
void tr2tls_push_self(uint64_t us_now)
|
void tr2tls_push_self(uint64_t us_now)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
|
uint64_t *new_array;
|
||||||
|
size_t new_alloc;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctx->nr_skipped_regions) {
|
||||||
|
ctx->nr_skipped_regions++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->nr_open_regions >= ctx->alloc) {
|
||||||
|
if (ctx->alloc >
|
||||||
|
SIZE_MAX / (2 * sizeof(*ctx->array_us_start))) {
|
||||||
|
ctx->nr_skipped_regions++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new_alloc = ctx->alloc * 2;
|
||||||
|
|
||||||
|
new_array = realloc(ctx->array_us_start,
|
||||||
|
new_alloc * sizeof(*ctx->array_us_start));
|
||||||
|
if (!new_array) {
|
||||||
|
ctx->nr_skipped_regions++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->array_us_start = new_array;
|
||||||
|
ctx->alloc = new_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
ALLOC_GROW(ctx->array_us_start, ctx->nr_open_regions + 1, ctx->alloc);
|
|
||||||
ctx->array_us_start[ctx->nr_open_regions++] = us_now;
|
ctx->array_us_start[ctx->nr_open_regions++] = us_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,6 +168,14 @@ void tr2tls_pop_self(void)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctx->nr_skipped_regions) {
|
||||||
|
ctx->nr_skipped_regions--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ctx->nr_open_regions)
|
if (!ctx->nr_open_regions)
|
||||||
BUG("no open regions in thread '%s'", ctx->thread_name);
|
BUG("no open regions in thread '%s'", ctx->thread_name);
|
||||||
|
|
||||||
|
|
@ -126,6 +186,9 @@ void tr2tls_pop_unwind_self(void)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
while (ctx->nr_open_regions > 1)
|
while (ctx->nr_open_regions > 1)
|
||||||
tr2tls_pop_self();
|
tr2tls_pop_self();
|
||||||
}
|
}
|
||||||
|
|
@ -136,6 +199,10 @@ uint64_t tr2tls_region_elasped_self(uint64_t us)
|
||||||
uint64_t us_start;
|
uint64_t us_start;
|
||||||
|
|
||||||
ctx = tr2tls_get_self();
|
ctx = tr2tls_get_self();
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return 0;
|
||||||
|
if (ctx->nr_skipped_regions)
|
||||||
|
return 0;
|
||||||
if (!ctx->nr_open_regions)
|
if (!ctx->nr_open_regions)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -155,6 +222,10 @@ uint64_t tr2tls_absolute_elapsed(uint64_t us)
|
||||||
static void tr2tls_key_destructor(void *payload)
|
static void tr2tls_key_destructor(void *payload)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = payload;
|
struct tr2tls_thread_ctx *ctx = payload;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
|
||||||
free((char *)ctx->thread_name);
|
free((char *)ctx->thread_name);
|
||||||
free(ctx->array_us_start);
|
free(ctx->array_us_start);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ struct tr2tls_thread_ctx {
|
||||||
uint64_t *array_us_start;
|
uint64_t *array_us_start;
|
||||||
size_t alloc;
|
size_t alloc;
|
||||||
size_t nr_open_regions; /* plays role of "nr" in ALLOC_GROW */
|
size_t nr_open_regions; /* plays role of "nr" in ALLOC_GROW */
|
||||||
|
size_t nr_skipped_regions;
|
||||||
int thread_id;
|
int thread_id;
|
||||||
struct tr2_timer_block timer_block;
|
struct tr2_timer_block timer_block;
|
||||||
struct tr2_counter_block counter_block;
|
struct tr2_counter_block counter_block;
|
||||||
|
|
@ -53,6 +54,12 @@ struct tr2tls_thread_ctx *tr2tls_create_self(const char *thread_base_name,
|
||||||
*/
|
*/
|
||||||
struct tr2tls_thread_ctx *tr2tls_get_self(void);
|
struct tr2tls_thread_ctx *tr2tls_get_self(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return true if the context is the non-allocating fallback used after an
|
||||||
|
* allocation failure. Callers must not modify a fallback context.
|
||||||
|
*/
|
||||||
|
int tr2tls_is_fallback(const struct tr2tls_thread_ctx *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return true if the current thread is the main thread.
|
* return true if the current thread is the main thread.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include "trace2/tr2_tls.h"
|
#include "trace2/tr2_tls.h"
|
||||||
#include "trace2/tr2_tmr.h"
|
#include "trace2/tr2_tmr.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
/* banned-die must be last. */
|
||||||
|
#include "banned-die.h"
|
||||||
|
|
||||||
#define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
@ -37,8 +39,11 @@ static struct tr2_timer_metadata tr2_timer_metadata[TRACE2_NUMBER_OF_TIMERS] = {
|
||||||
void tr2_start_timer(enum trace2_timer_id tid)
|
void tr2_start_timer(enum trace2_timer_id tid)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
struct tr2_timer *t = &ctx->timer_block.timer[tid];
|
struct tr2_timer *t;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
t = &ctx->timer_block.timer[tid];
|
||||||
t->recursion_count++;
|
t->recursion_count++;
|
||||||
if (t->recursion_count > 1)
|
if (t->recursion_count > 1)
|
||||||
return; /* ignore recursive starts */
|
return; /* ignore recursive starts */
|
||||||
|
|
@ -49,10 +54,13 @@ void tr2_start_timer(enum trace2_timer_id tid)
|
||||||
void tr2_stop_timer(enum trace2_timer_id tid)
|
void tr2_stop_timer(enum trace2_timer_id tid)
|
||||||
{
|
{
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
struct tr2_timer *t = &ctx->timer_block.timer[tid];
|
struct tr2_timer *t;
|
||||||
uint64_t ns_now;
|
uint64_t ns_now;
|
||||||
uint64_t ns_interval;
|
uint64_t ns_interval;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
|
t = &ctx->timer_block.timer[tid];
|
||||||
assert(t->recursion_count > 0);
|
assert(t->recursion_count > 0);
|
||||||
|
|
||||||
t->recursion_count--;
|
t->recursion_count--;
|
||||||
|
|
@ -90,6 +98,8 @@ void tr2_update_final_timers(void)
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
enum trace2_timer_id tid;
|
enum trace2_timer_id tid;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
if (!ctx->used_any_timer)
|
if (!ctx->used_any_timer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -136,6 +146,8 @@ void tr2_emit_per_thread_timers(tr2_tgt_evt_timer_t *fn_apply)
|
||||||
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
struct tr2tls_thread_ctx *ctx = tr2tls_get_self();
|
||||||
enum trace2_timer_id tid;
|
enum trace2_timer_id tid;
|
||||||
|
|
||||||
|
if (tr2tls_is_fallback(ctx))
|
||||||
|
return;
|
||||||
if (!ctx->used_any_per_thread_timer)
|
if (!ctx->used_any_per_thread_timer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue