Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: TML <tarantool-patches@dev.tarantool.org>
Subject: Re: [Tarantool-patches] [PATCH v4 4/4] crash: report crash data to the feedback server
Date: Sun, 20 Dec 2020 16:16:46 +0100	[thread overview]
Message-ID: <96e492a5-3866-91ac-801b-c26c1fce96e2@tarantool.org> (raw)
In-Reply-To: <20201216203106.GC14556@grain>

I see you didn't push it on the branch. Please, do. Otherwise I can't
validate if it works.

See 6 comments below.

> diff --git a/src/box/box.cc b/src/box/box.cc
> index a8bc3471d..27079fd46 100644
> --- a/src/box/box.cc
> +++ b/src/box/box.cc
> @@ -1213,6 +1214,21 @@ box_set_prepared_stmt_cache_size(void)
>  	return 0;
>  }
>  
> +void
> +box_set_crash_params(void)
> +{
> +	const char *host = cfg_gets("feedback_host");
> +	bool is_enabled_1 = cfg_getb("feedback_enabled");
> +	bool is_enabled_2 = cfg_getb("feedback_crashinfo");
> +
> +	if (host != NULL && strlen(host) >= CRASH_FEEDBACK_HOST_MAX) {
> +		tnt_raise(ClientError, ER_CFG, "feedback_host",
> +			  "the address is too long");

1. Please, don't use exceptions in the new code. We are getting rid
of them, and such changes complicate it in future.

> +	}
> +
> +	crash_cfg_set_params(host, is_enabled_1 && is_enabled_2);

2. Just 'crash_cfg', please. We have lots of 'cfg' functions for
various modules, and none of them has 'set_params' suffix. Probably
because this is what 'cfg' means anyway.

> +}
> diff --git a/src/lib/core/crash.c b/src/lib/core/crash.c
> index a15a13e8e..f6dd91987 100644
> --- a/src/lib/core/crash.c
> +++ b/src/lib/core/crash.c
> @@ -81,13 +96,75 @@ static struct crash_info {
>  	int sicode;
>  #ifdef ENABLE_BACKTRACE
>  	/*
> -	 * 4K of memory should be enough to keep the backtrace.
> +	 * 1K of memory should be enough to keep the backtrace.
>  	 * In worst case it gonna be simply trimmed.
>  	 */
> -	char backtrace_buf[4096];
> +	char backtrace_buf[1024];

3. I am begging you. Please. Stop mixing independent changes with
each other. Please. How can I ask otherwise? What can I do to
explain this? How can I help to understand?

>  #endif> @@ -126,6 +209,196 @@ crash_collect(int signo, siginfo_t *siginfo, void *ucontext)
>  	return cinfo;
>  }
>  
> +/**
> + * Mark an environment that we're in crashinfo handling, this
> + * allows us to escape recursive attempts to send report,
> + * if the action of sending report is failing itself.
> + */
> +static int
> +crash_mark_env_mode(void)
> +{
> +	const char *env_name = "TT_CRASHINFO_MODE";
> +	if (getenv(env_name) != NULL) {
> +		pr_crit("recursive failure detected");
> +		return -1;
> +	}
> +
> +	if (setenv(env_name, "y", 0) != 0) {
> +		pr_crit("unable to setup %s", env_name);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * Report crash information to the feedback daemon
> + * (ie send it to feedback daemon).
> + */
> +static void
> +crash_report_feedback_daemon(struct crash_info *cinfo)
> +{
> +	if (crash_mark_env_mode() != 0)
> +		return;
> +
> +	/*
> +	 * Update to a new number if format get changed.
> +	 */
> +	const int crashinfo_version = 1;
> +
> +	char *p = static_alloc(SMALL_STATIC_SIZE);
> +	char *e = &p[SMALL_STATIC_SIZE - 1];
> +	char *head = p;
> +	char *tail = &p[SMALL_STATIC_SIZE - 8];
> +
> +	/*
> +	 * Note that while we encode the report we
> +	 * intensively use a tail of the allocated
> +	 * buffer as a temporary store.
> +	 */
> +
> +#define snprintf_safe(__end, __fmt, ...)				\
> +	do {								\
> +		size_t size = (char *)(void *)__end - p;		\

4. Please, remove the double cast. You can use (char *) as is. Here and
in other places.

> +		p += snprintf(p, size, __fmt, ##__VA_ARGS__);		\
> +		if (p >= (char *)(void *)__end)				\
> +			goto out;					\
> +	} while (0)
> +
> +	/*
> +	 * Lets reuse tail of the buffer as a temp space.
> +	 */
> +	struct utsname *uname_ptr = (void *)&tail[-sizeof(struct utsname)];
> +	if (p >= (char *)(void *)uname_ptr)
> +		goto out;
> +
> +	if (uname(uname_ptr) != 0) {
> +		pr_syserr("uname call failed, ignore");
> +		memset(uname_ptr, 0, sizeof(struct utsname));
> +	}
> +
> +	snprintf_safe(uname_ptr, "{");
> +	snprintf_safe(uname_ptr, "\"uname\":{");
> +	snprintf_safe(uname_ptr, "\"sysname\":\"%s\",", uname_ptr->sysname);
> +	/*
> +	 * nodename might a sensitive information, skip.

5. 'might' what? You missed a verb.

> +	 */
> +	snprintf_safe(uname_ptr, "\"release\":\"%s\",", uname_ptr->release);
> +	snprintf_safe(uname_ptr, "\"version\":\"%s\",", uname_ptr->version);
> +	snprintf_safe(uname_ptr, "\"machine\":\"%s\"", uname_ptr->machine);
> +	snprintf_safe(uname_ptr, "},");
> +
> +	snprintf_safe(e, "\"build\":{");
> +	snprintf_safe(e, "\"version\":\"%s\",", PACKAGE_VERSION);
> +	snprintf_safe(e, "\"cmake_type\":\"%s\"", BUILD_INFO);
> +	snprintf_safe(e, "},");
> +
> +	snprintf_safe(e, "\"signal\":{");
> +	snprintf_safe(e, "\"signo\":%d,", cinfo->signo);
> +	snprintf_safe(e, "\"si_code\":%d,", cinfo->sicode);
> +	if (cinfo->signo == SIGSEGV) {
> +		if (cinfo->sicode == SEGV_MAPERR) {
> +			snprintf_safe(e, "\"si_code_str\":\"%s\",",
> +				      "SEGV_MAPERR");
> +		} else if (cinfo->sicode == SEGV_ACCERR) {
> +			snprintf_safe(e, "\"si_code_str\":\"%s\",",
> +				      "SEGV_ACCERR");
> +		}
> +		snprintf_safe(e, "\"si_addr\":\"0x%llx\",",
> +			      (long long)cinfo->siaddr);
> +	}
> +
> +#ifdef ENABLE_BACKTRACE
> +	/*
> +	 * The backtrace itself is encoded into base64 form
> +	 * since it might have arbitrary symbols not suitable
> +	 * for json encoding (newlines and etc).
> +	 */
> +	size_t bt_len = strlen(cinfo->backtrace_buf);
> +	size_t bt_elen = base64_bufsize(bt_len, BASE64_NOWRAP);
> +	char *bt_base64 = &tail[-bt_elen];
> +	if (p >= bt_base64)
> +		goto out;
> +	base64_encode(cinfo->backtrace_buf, bt_len,
> +		      bt_base64, bt_elen, BASE64_NOWRAP);
> +	bt_base64[bt_elen] = '\0';
> +	snprintf_safe(bt_base64, "\"backtrace\":\"%s\",", bt_base64);
> +#endif
> +
> +	/* 64 bytes should be enough for longest localtime */
> +	char *timestamp_rt_str = &tail[-64];
> +	if (p >= timestamp_rt_str)
> +		goto out;
> +	ns_to_localtime(cinfo->timestamp_rt, timestamp_rt_str, 64);
> +	snprintf_safe(timestamp_rt_str, "\"timestamp\":\"%s\"", timestamp_rt_str);
> +	snprintf_safe(timestamp_rt_str, "}");
> +	snprintf_safe(timestamp_rt_str, "}");
> +
> +	size_t report_len = p - head;
> +	size_t report_elen = base64_bufsize(report_len, BASE64_NOWRAP);
> +
> +	char *report_base64 = &tail[-report_elen];
> +	if (p >= report_base64)
> +		goto out;
> +	base64_encode(head, report_len, report_base64,
> +		      report_elen, BASE64_NOWRAP);
> +	report_base64[report_elen] = '\0';
> +
> +	/*
> +	 * Encoded report now sits at report_base64 position,
> +	 * at the tail of 'small' static buffer. Lets prepare
> +	 * the script to run.
> +	 */
> +	p = head;
> +	snprintf_safe(report_base64,
> +		      "require(\'http.client\').post(\'%s\',"
> +		      "'{\"crashdump\":{\"version\":\"%d\","
> +		      "\"data\": \"%s\"}}',{timeout=1});"
> +		      "os.exit(1);", feedback_host,
> +		      crashinfo_version, report_base64);

6. I think now I understood all these buffer allocs. Except
that I still don't understand why is tail initialized as

	char *tail = &p[SMALL_STATIC_SIZE - 8];

instead of just `tail = end;`.

  reply	other threads:[~2020-12-20 15:16 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-10 16:18 [Tarantool-patches] [PATCH v4 0/4] crash: implement sending feedback Cyrill Gorcunov
2020-12-10 16:18 ` [Tarantool-patches] [PATCH v4 1/4] util: introduce strlcpy helper Cyrill Gorcunov
2020-12-11  7:34   ` Serge Petrenko
2020-12-11  7:58     ` Serge Petrenko
2020-12-11 10:04       ` Cyrill Gorcunov
2020-12-11 11:07         ` Serge Petrenko
2020-12-11 11:38           ` Cyrill Gorcunov
2020-12-14 22:54             ` Vladislav Shpilevoy
2020-12-14 22:54   ` Vladislav Shpilevoy
2020-12-15  8:47     ` Cyrill Gorcunov
2020-12-10 16:18 ` [Tarantool-patches] [PATCH v4 2/4] backtrace: allow to specify destination buffer Cyrill Gorcunov
2020-12-11  7:50   ` Serge Petrenko
2020-12-10 16:18 ` [Tarantool-patches] [PATCH v4 3/4] crash: move fatal signal handling in Cyrill Gorcunov
2020-12-11  9:31   ` Serge Petrenko
2020-12-11 10:38     ` Cyrill Gorcunov
2020-12-11 11:12       ` Serge Petrenko
2020-12-14 22:54   ` Vladislav Shpilevoy
2020-12-15  8:16     ` Cyrill Gorcunov
2020-12-20 14:48       ` Vladislav Shpilevoy
2020-12-20 15:49         ` Cyrill Gorcunov
2020-12-20 16:07           ` Vladislav Shpilevoy
2020-12-20 16:58             ` Cyrill Gorcunov
2020-12-20 15:45   ` Vladislav Shpilevoy
2020-12-10 16:18 ` [Tarantool-patches] [PATCH v4 4/4] crash: report crash data to the feedback server Cyrill Gorcunov
2020-12-11 12:57   ` Serge Petrenko
2020-12-12 16:19     ` Cyrill Gorcunov
2020-12-12 17:07       ` Cyrill Gorcunov
2020-12-14  9:41         ` Serge Petrenko
2020-12-14 22:54   ` Vladislav Shpilevoy
2020-12-16 11:16     ` Cyrill Gorcunov
2020-12-16 20:31       ` Cyrill Gorcunov
2020-12-20 15:16         ` Vladislav Shpilevoy [this message]
2020-12-20 18:26           ` Cyrill Gorcunov
2020-12-20 14:48       ` Vladislav Shpilevoy
2020-12-20 18:21         ` Cyrill Gorcunov
2020-12-20 18:41           ` Vladislav Shpilevoy
2020-12-20 19:16             ` Cyrill Gorcunov
2020-12-21 17:01               ` Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=96e492a5-3866-91ac-801b-c26c1fce96e2@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=gorcunov@gmail.com \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v4 4/4] crash: report crash data to the feedback server' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox