perf top: Stop using exit()

Just return to the perf main() routine so that an unified exit path can
be followed and resources released, helping in finding memory leaks.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ro8oeodo96490nrhcph57atr@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 152fefa9
...@@ -68,6 +68,8 @@ ...@@ -68,6 +68,8 @@
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/types.h> #include <linux/types.h>
static volatile int done;
static void perf_top__update_print_entries(struct perf_top *top) static void perf_top__update_print_entries(struct perf_top *top)
{ {
if (top->print_entries > 9) if (top->print_entries > 9)
...@@ -431,8 +433,10 @@ static int perf_top__key_mapped(struct perf_top *top, int c) ...@@ -431,8 +433,10 @@ static int perf_top__key_mapped(struct perf_top *top, int c)
return 0; return 0;
} }
static void perf_top__handle_keypress(struct perf_top *top, int c) static bool perf_top__handle_keypress(struct perf_top *top, int c)
{ {
bool ret = true;
if (!perf_top__key_mapped(top, c)) { if (!perf_top__key_mapped(top, c)) {
struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
struct termios tc, save; struct termios tc, save;
...@@ -453,7 +457,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) ...@@ -453,7 +457,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
tcsetattr(0, TCSAFLUSH, &save); tcsetattr(0, TCSAFLUSH, &save);
if (!perf_top__key_mapped(top, c)) if (!perf_top__key_mapped(top, c))
return; return ret;
} }
switch (c) { switch (c) {
...@@ -515,7 +519,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) ...@@ -515,7 +519,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
printf("exiting.\n"); printf("exiting.\n");
if (top->dump_symtab) if (top->dump_symtab)
perf_session__fprintf_dsos(top->session, stderr); perf_session__fprintf_dsos(top->session, stderr);
exit(0); ret = false;
break;
case 's': case 's':
perf_top__prompt_symbol(top, "Enter details symbol"); perf_top__prompt_symbol(top, "Enter details symbol");
break; break;
...@@ -538,6 +543,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c) ...@@ -538,6 +543,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
default: default:
break; break;
} }
return ret;
} }
static void perf_top__sort_new_samples(void *arg) static void perf_top__sort_new_samples(void *arg)
...@@ -579,8 +586,7 @@ static void *display_thread_tui(void *arg) ...@@ -579,8 +586,7 @@ static void *display_thread_tui(void *arg)
perf_evlist__tui_browse_hists(top->evlist, help, &hbt, perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
&top->session->header.env); &top->session->header.env);
exit_browser(0); done = 1;
exit(0);
return NULL; return NULL;
} }
...@@ -604,7 +610,7 @@ static void *display_thread(void *arg) ...@@ -604,7 +610,7 @@ static void *display_thread(void *arg)
/* trash return*/ /* trash return*/
getc(stdin); getc(stdin);
while (1) { while (!done) {
perf_top__print_sym_table(top); perf_top__print_sym_table(top);
/* /*
* Either timeout expired or we got an EINTR due to SIGWINCH, * Either timeout expired or we got an EINTR due to SIGWINCH,
...@@ -618,15 +624,14 @@ static void *display_thread(void *arg) ...@@ -618,15 +624,14 @@ static void *display_thread(void *arg)
continue; continue;
/* Fall trhu */ /* Fall trhu */
default: default:
goto process_hotkey; c = getc(stdin);
tcsetattr(0, TCSAFLUSH, &save);
if (perf_top__handle_keypress(top, c))
goto repeat;
done = 1;
} }
} }
process_hotkey:
c = getc(stdin);
tcsetattr(0, TCSAFLUSH, &save);
perf_top__handle_keypress(top, c);
goto repeat;
return NULL; return NULL;
} }
...@@ -705,7 +710,7 @@ static void perf_event__process_sample(struct perf_tool *tool, ...@@ -705,7 +710,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
} }
if (!machine) { if (!machine) {
pr_err("%u unprocessable samples recorded.\n", pr_err("%u unprocessable samples recorded.\r",
top->session->stats.nr_unprocessable_samples++); top->session->stats.nr_unprocessable_samples++);
return; return;
} }
...@@ -868,7 +873,7 @@ static void perf_top__mmap_read(struct perf_top *top) ...@@ -868,7 +873,7 @@ static void perf_top__mmap_read(struct perf_top *top)
perf_top__mmap_read_idx(top, i); perf_top__mmap_read_idx(top, i);
} }
static void perf_top__start_counters(struct perf_top *top) static int perf_top__start_counters(struct perf_top *top)
{ {
char msg[512]; char msg[512];
struct perf_evsel *counter; struct perf_evsel *counter;
...@@ -900,11 +905,10 @@ static void perf_top__start_counters(struct perf_top *top) ...@@ -900,11 +905,10 @@ static void perf_top__start_counters(struct perf_top *top)
goto out_err; goto out_err;
} }
return; return 0;
out_err: out_err:
exit_browser(0); return -1;
exit(0);
} }
static int perf_top__setup_sample_type(struct perf_top *top) static int perf_top__setup_sample_type(struct perf_top *top)
...@@ -948,7 +952,11 @@ static int __cmd_top(struct perf_top *top) ...@@ -948,7 +952,11 @@ static int __cmd_top(struct perf_top *top)
else else
perf_event__synthesize_threads(&top->tool, perf_event__process, perf_event__synthesize_threads(&top->tool, perf_event__process,
&top->session->machines.host); &top->session->machines.host);
perf_top__start_counters(top);
ret = perf_top__start_counters(top);
if (ret)
goto out_delete;
top->session->evlist = top->evlist; top->session->evlist = top->evlist;
perf_session__set_id_hdr_size(top->session); perf_session__set_id_hdr_size(top->session);
...@@ -968,10 +976,11 @@ static int __cmd_top(struct perf_top *top) ...@@ -968,10 +976,11 @@ static int __cmd_top(struct perf_top *top)
perf_top__mmap_read(top); perf_top__mmap_read(top);
ret = -1;
if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
display_thread), top)) { display_thread), top)) {
ui__error("Could not create display thread.\n"); ui__error("Could not create display thread.\n");
exit(-1); goto out_delete;
} }
if (top->realtime_prio) { if (top->realtime_prio) {
...@@ -980,11 +989,11 @@ static int __cmd_top(struct perf_top *top) ...@@ -980,11 +989,11 @@ static int __cmd_top(struct perf_top *top)
param.sched_priority = top->realtime_prio; param.sched_priority = top->realtime_prio;
if (sched_setscheduler(0, SCHED_FIFO, &param)) { if (sched_setscheduler(0, SCHED_FIFO, &param)) {
ui__error("Could not set realtime priority.\n"); ui__error("Could not set realtime priority.\n");
exit(-1); goto out_delete;
} }
} }
while (1) { while (!done) {
u64 hits = top->samples; u64 hits = top->samples;
perf_top__mmap_read(top); perf_top__mmap_read(top);
...@@ -993,11 +1002,12 @@ static int __cmd_top(struct perf_top *top) ...@@ -993,11 +1002,12 @@ static int __cmd_top(struct perf_top *top)
ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
} }
ret = 0;
out_delete: out_delete:
perf_session__delete(top->session); perf_session__delete(top->session);
top->session = NULL; top->session = NULL;
return 0; return ret;
} }
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment