BUG/MINOR: trace: stop rewriting argv with -dt

When using trace with -dt, the trace_parse_cmd() function is doing a
strtok which write \0 into the argv string.

When using the mworker mode, and reloading, argv was modified and the
trace won't work anymore because the first : is replaced by a '\0'.

This patch fixes the issue by allocating a temporary string so we don't
modify the source string directly. It also replace strtok by its
reentrant version strtok_r.

Must be backported as far as 2.9.
This commit is contained in:
William Lallemand 2024-10-29 10:50:27 +01:00
parent e240be5495
commit 596db3ef86
2 changed files with 20 additions and 5 deletions

View File

@ -190,7 +190,7 @@ void trace_no_cb(enum trace_level level, uint64_t mask, const struct trace_sourc
void trace_register_source(struct trace_source *source); void trace_register_source(struct trace_source *source);
int trace_parse_cmd(char *arg, char **errmsg); int trace_parse_cmd(const char *arg_src, char **errmsg);
/* return a single char to describe a trace state */ /* return a single char to describe a trace state */
static inline char trace_state_char(enum trace_state st) static inline char trace_state_char(enum trace_state st)

View File

@ -966,11 +966,22 @@ void _trace_parse_cmd(struct trace_source *src, int level, int verbosity)
* *
* Returns 0 on success else non-zero. * Returns 0 on success else non-zero.
*/ */
int trace_parse_cmd(char *arg, char **errmsg) int trace_parse_cmd(const char *arg_src, char **errmsg)
{ {
char *str; char *str;
char *arg, *oarg;
char *saveptr;
if (arg_src) {
/* keep a copy of the ptr for strtok */
oarg = arg = strdup(arg_src);
if (!arg) { if (!arg) {
memprintf(errmsg, "Can't allocate !");
return 1;
}
}
if (!arg_src) {
/* No trace specification, activate all sources on error level. */ /* No trace specification, activate all sources on error level. */
struct trace_source *src = NULL; struct trace_source *src = NULL;
@ -979,7 +990,7 @@ int trace_parse_cmd(char *arg, char **errmsg)
return 0; return 0;
} }
while ((str = strtok(arg, ","))) { while ((str = strtok_r(arg, ",", &saveptr))) {
struct trace_source *src = NULL; struct trace_source *src = NULL;
char *field, *name; char *field, *name;
char *sep; char *sep;
@ -1000,6 +1011,7 @@ int trace_parse_cmd(char *arg, char **errmsg)
src = trace_find_source(name); src = trace_find_source(name);
if (!src) { if (!src) {
memprintf(errmsg, "unknown trace source '%s'", name); memprintf(errmsg, "unknown trace source '%s'", name);
ha_free(&oarg);
return 1; return 1;
} }
} }
@ -1022,6 +1034,7 @@ int trace_parse_cmd(char *arg, char **errmsg)
level = trace_parse_level(field); level = trace_parse_level(field);
if (level < 0) { if (level < 0) {
memprintf(errmsg, "no such trace level '%s', available levels are 'error', 'user', 'proto', 'state', 'data', and 'developer'", field); memprintf(errmsg, "no such trace level '%s', available levels are 'error', 'user', 'proto', 'state', 'data', and 'developer'", field);
ha_free(&oarg);
return 1; return 1;
} }
} }
@ -1033,6 +1046,7 @@ int trace_parse_cmd(char *arg, char **errmsg)
field = str; field = str;
if (strchr(field, ':')) { if (strchr(field, ':')) {
memprintf(errmsg, "too many double-colon separators in trace definition"); memprintf(errmsg, "too many double-colon separators in trace definition");
ha_free(&oarg);
return 1; return 1;
} }
@ -1049,6 +1063,7 @@ int trace_parse_cmd(char *arg, char **errmsg)
memprintf(errmsg, "%s, %s'%s'", *errmsg, (nd + 1)->name ? "" : "and ", nd->name); memprintf(errmsg, "%s, %s'%s'", *errmsg, (nd + 1)->name ? "" : "and ", nd->name);
} }
ha_free(&oarg);
return 1; return 1;
} }
@ -1064,7 +1079,7 @@ int trace_parse_cmd(char *arg, char **errmsg)
/* Reset arg to NULL for strtok. */ /* Reset arg to NULL for strtok. */
arg = NULL; arg = NULL;
} }
ha_free(&oarg);
return 0; return 0;
} }