From: "Steven Rostedt (Google)" <rostedt@xxxxxxxxxxx> Have trace-cmd stream periodically signal the recorder tasks to flush some output, otherwise it will look empty for a long time (especially with the default setting of a 50 percent buffering, where the ring buffers will not return read until they are half full). Add a "finish" flag to tracecmd_flush_recording() that will keep the old behavior when set, but when not set, it will only do a single tracefs_cpu_flush() that will output some data, but not all of it. Use the SIGUSR2 to signal the recorder tasks to do the flush. Signed-off-by: Steven Rostedt (Google) <rostedt@xxxxxxxxxxx> --- .../include/private/trace-cmd-private.h | 2 +- lib/trace-cmd/trace-recorder.c | 10 ++++- tracecmd/trace-record.c | 41 +++++++++++++++---- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index 2cb6f35cb250..e8b0989ac67e 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -378,7 +378,7 @@ struct tracecmd_recorder *tracecmd_create_buffer_recorder_maxkb(const char *file int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long sleep); void tracecmd_stop_recording(struct tracecmd_recorder *recorder); -long tracecmd_flush_recording(struct tracecmd_recorder *recorder); +long tracecmd_flush_recording(struct tracecmd_recorder *recorder, bool finish); enum tracecmd_msg_flags { TRACECMD_MSG_FL_USE_TCP = 1 << 0, diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index bb02f7b8ee11..79b95ce1193d 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -366,13 +366,19 @@ static long move_data(struct tracecmd_recorder *recorder) return ret; } -long tracecmd_flush_recording(struct tracecmd_recorder *recorder) +long tracecmd_flush_recording(struct tracecmd_recorder *recorder, bool finish) { char buf[recorder->subbuf_size]; long total = 0; long wrote = 0; long ret; + if (!recorder) + return 0; + + if (!finish) + return tracefs_cpu_flush_write(recorder->tcpu, recorder->fd); + set_nonblock(recorder); do { @@ -421,7 +427,7 @@ int tracecmd_start_recording(struct tracecmd_recorder *recorder, unsigned long s } while (!recorder->stop); /* Flush out the rest */ - ret = tracecmd_flush_recording(recorder); + ret = tracecmd_flush_recording(recorder, true); if (ret < 0) return ret; diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index cc6f27bf22e8..a03d334a65d5 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -1641,12 +1641,21 @@ static inline void ptrace_attach(struct buffer_instance *instance, int pid) { } static void trace_or_sleep(enum trace_type type, bool pwait) { struct timeval tv = { 1 , 0 }; + int i; if (pwait) ptrace_wait(type); - else if (type & TRACE_TYPE_STREAM) - trace_stream_read(pids, recorder_threads, &tv); - else + else if (type & TRACE_TYPE_STREAM) { + /* Returns zero if it did not read anything (and did a sleep) */ + if (trace_stream_read(pids, recorder_threads, &tv) > 0) + return; + /* Force a flush if nothing was read (including on errors) */ + for (i = 0; i < recorder_threads; i++) { + if (pids[i].pid > 0) { + kill(pids[i].pid, SIGUSR2); + } + } + } else sleep(10); } @@ -3156,7 +3165,7 @@ static void expand_event_list(void) expand_event_instance(instance); } -static void finish(int sig) +static void finish(void) { /* all done */ if (recorder) @@ -3164,6 +3173,23 @@ static void finish(int sig) finished = 1; } +static void flush(void) +{ + if (recorder) + tracecmd_flush_recording(recorder, false); +} + +static void do_sig(int sig) +{ + switch (sig) { + case SIGUSR1: + case SIGINT: + return finish(); + case SIGUSR2: + return flush(); + } +} + static struct addrinfo *do_getaddrinfo(const char *host, unsigned int port, enum port_type type) { @@ -3405,7 +3431,8 @@ static int create_recorder(struct buffer_instance *instance, int cpu, return pid; signal(SIGINT, SIG_IGN); - signal(SIGUSR1, finish); + signal(SIGUSR1, do_sig); + signal(SIGUSR2, do_sig); if (rt_prio) set_prio(rt_prio); @@ -3451,7 +3478,7 @@ static int create_recorder(struct buffer_instance *instance, int cpu, die ("can't create recorder"); if (type == TRACE_TYPE_EXTRACT) { - ret = tracecmd_flush_recording(recorder); + ret = tracecmd_flush_recording(recorder, true); tracecmd_free_recorder(recorder); recorder = NULL; return ret; @@ -6945,7 +6972,7 @@ static void record_trace(int argc, char **argv, allocate_seq(); if (type & (TRACE_TYPE_RECORD | TRACE_TYPE_STREAM)) { - signal(SIGINT, finish); + signal(SIGINT, do_sig); if (!latency) start_threads(type, ctx); } -- 2.35.1