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.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
152fefa921
commit
11859e8217
|
@ -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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@ repeat:
|
||||||
/* 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 @@ repeat:
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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 @@ try_again:
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
param.sched_priority = top->realtime_prio;
|
param.sched_priority = top->realtime_prio;
|
||||||
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
|
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
|
||||||
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)
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue