When trace-cmd runs a command, specified with the "-F" flag, it forks a child process and executes the command in its context. This child process receives a full copy of the parents memory at the moment of fork(). When it modifies this copy, the parent memory is not affected. Calling the function update_task_filter() in the child context will operate on a valid data, but will not update anything in the parent's databases. Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@xxxxxxxxx> --- tracecmd/trace-record.c | 64 +++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 1e4d38fa..ae8a5745 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -11,6 +11,7 @@ #include <stdarg.h> #include <getopt.h> #include <time.h> +#include <semaphore.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> @@ -1187,10 +1188,12 @@ static void get_filter_pid_maps(void) } } -static void update_task_filter(void) +static void update_task_filter(int pid) { struct buffer_instance *instance; - int pid = getpid(); + + if (pid < 0) + pid = getpid(); if (no_filter) return; @@ -1487,18 +1490,40 @@ static int change_user(const char *user) return 0; } +#define TRACE_RUN_SEM "trace_cmd_semaphore_run" +#define TRACE_INIT_SEM "trace_cmd_semaphore_init" static void run_cmd(enum trace_type type, const char *user, int argc, char **argv) { + sem_t *sem_init = SEM_FAILED; + sem_t *sem_run = SEM_FAILED; + char *die_log = NULL; int status; int pid; - if ((pid = fork()) < 0) - die("failed to fork"); + sem_init = sem_open(TRACE_INIT_SEM, O_CREAT, S_IRUSR|S_IWUSR, 0); + if (sem_init == SEM_FAILED) { + die_log = "failed to init trace_cmd init semaphore"; + goto out; + } + + sem_run = sem_open(TRACE_RUN_SEM, O_CREAT, S_IRUSR|S_IWUSR, 0); + if (sem_run == SEM_FAILED) { + die_log = "failed to init trace_cmd run semaphore"; + goto out; + + } + + if ((pid = fork()) < 0) { + die_log = "failed to fork"; + goto out; + } if (!pid) { /* child */ - update_task_filter(); + sem_wait(sem_init); tracecmd_enable_tracing(); enable_ptrace(); + sem_post(sem_run); + /* * If we are using stderr for stdout, switch * it back to the saved stdout for the code we run. @@ -1519,12 +1544,27 @@ static void run_cmd(enum trace_type type, const char *user, int argc, char **arg die("Failed to exec %s", argv[0]); } } - if (do_ptrace) { - add_filter_pid(pid, 0); - ptrace_attach(pid); + update_task_filter(pid); + sem_post(sem_init); + sem_wait(sem_run); + + if (do_ptrace) ptrace_wait(type); - } else + else trace_waitpid(type, pid, &status, 0); + +out: + if (sem_init != SEM_FAILED) { + sem_close(sem_init); + sem_unlink(TRACE_INIT_SEM); + } + if (sem_run != SEM_FAILED) { + sem_close(sem_run); + sem_unlink(TRACE_RUN_SEM); + } + + if (die_log) + die(die_log); } static void @@ -6285,7 +6325,7 @@ static void record_trace(int argc, char **argv, if (!latency) start_threads(type, ctx); } else { - update_task_filter(); + update_task_filter(-1); tracecmd_enable_tracing(); exit(0); } @@ -6293,11 +6333,11 @@ static void record_trace(int argc, char **argv, if (ctx->run_command) { run_cmd(type, ctx->user, (argc - optind) - 1, &argv[optind + 1]); } else if (ctx->instance && is_agent(ctx->instance)) { - update_task_filter(); + update_task_filter(-1); tracecmd_enable_tracing(); tracecmd_msg_wait_close(ctx->instance->msg_handle); } else { - update_task_filter(); + update_task_filter(-1); tracecmd_enable_tracing(); /* We don't ptrace ourself */ if (do_ptrace && filter_pids) { -- 2.26.2