From 4ce5fb0f282acaace0a7a7386536c6574fcfea6a Mon Sep 17 00:00:00 2001 From: Mohamad Gebai Date: Mon, 27 Mar 2017 09:34:13 +0200 Subject: [PATCH 1/5] Add better error handling A shared object should never exit(). Signed-off-by: Mohamad Gebai --- src/libperf.c | 62 +++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/libperf.c b/src/libperf.c index f9e51b8..9712e6f 100644 --- a/src/libperf.c +++ b/src/libperf.c @@ -156,19 +156,19 @@ libperf_initialize(pid_t pid, int cpu) struct libperf_data *pd = malloc(sizeof(struct libperf_data)); - if (pd == NULL) - { - perror("malloc"); - exit(EXIT_FAILURE); - } + if (pd == NULL) { + goto error; + } - if (pid == -1) + if (pid == -1) { pid = gettid(); + } pd->group = -1; - for (i = 0; i < __LIBPERF_ARRAY_SIZE(pd->fds); i++) + for (i = 0; i < __LIBPERF_ARRAY_SIZE(pd->fds); i++) { pd->fds[i] = -1; + } pd->pid = pid; pd->cpu = cpu; @@ -178,11 +178,9 @@ libperf_initialize(pid_t pid, int cpu) struct perf_event_attr *attrs = malloc(nr_counters * sizeof(struct perf_event_attr)); - if(attrs == NULL) - { - perror("malloc"); - exit(EXIT_FAILURE); - } + if(attrs == NULL) { + goto error; + } memcpy(attrs, default_attrs, sizeof(default_attrs)); pd->attrs = attrs; @@ -192,29 +190,39 @@ libperf_initialize(pid_t pid, int cpu) open(logname, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - assert(fd != -1); - pd->log = fdopen(fd, "a"); + if (fd == -1) { + goto error; + } - assert(pd->log != NULL); + pd->log = fdopen(fd, "a"); - for (i = 0; i < nr_counters; i++) - { - attrs[i].size = sizeof(struct perf_event_attr); - attrs[i].inherit = 1; /* default */ - attrs[i].disabled = 1; /* disable them now... */ - attrs[i].enable_on_exec = 0; - pd->fds[i] = sys_perf_event_open(&attrs[i], pid, cpu, -1, 0); - if (pd->fds[i] < 0) - { - fprintf(stderr, "At event %d/%d\n", i, nr_counters); - perror("sys_perf_event_open"); - exit(EXIT_FAILURE); + if (pd->log == NULL) { + goto error; } + for (i = 0; i < nr_counters; i++) { + attrs[i].size = sizeof(struct perf_event_attr); + attrs[i].inherit = 1; /* default */ + attrs[i].disabled = 1; /* disable them now... */ + attrs[i].enable_on_exec = 0; + pd->fds[i] = sys_perf_event_open(&attrs[i], pid, cpu, -1, 0); + if (pd->fds[i] < 0) { + free(attrs); + goto close; } + } pd->wall_start = rdclock(); return pd; + +close: + close(fd); + close(pd->log); + for (i = 0; i < nr_counters; i++) { + close(pd->fds[i]); + } +error: + return NULL; } /* thread safe */ From 948d133d9e4731dabfeaa0bfd087193d4b87a54e Mon Sep 17 00:00:00 2001 From: Mohamad Gebai Date: Mon, 27 Mar 2017 13:50:21 +0200 Subject: [PATCH 2/5] Free previous allocations if initialization fails Signed-off-by: Mohamad Gebai --- src/libperf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libperf.c b/src/libperf.c index 9712e6f..f80ea6f 100644 --- a/src/libperf.c +++ b/src/libperf.c @@ -207,7 +207,6 @@ libperf_initialize(pid_t pid, int cpu) attrs[i].enable_on_exec = 0; pd->fds[i] = sys_perf_event_open(&attrs[i], pid, cpu, -1, 0); if (pd->fds[i] < 0) { - free(attrs); goto close; } } @@ -222,6 +221,14 @@ libperf_initialize(pid_t pid, int cpu) close(pd->fds[i]); } error: + if (attrs) { + free(attrs); + attrs = NULL; + } + if (pd) { + free(pd); + pd = NULL; + } return NULL; } From 52cdf3d08e3ae26b48d74f4fa75cf9db24993afc Mon Sep 17 00:00:00 2001 From: Mohamad Gebai Date: Mon, 27 Mar 2017 13:51:16 +0200 Subject: [PATCH 3/5] Update example to use initialize return value Signed-off-by: Mohamad Gebai --- src/libperf_example.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libperf_example.c b/src/libperf_example.c index 6615436..416f17e 100644 --- a/src/libperf_example.c +++ b/src/libperf_example.c @@ -32,6 +32,10 @@ int main(int argc, char *argv[]) { struct libperf_data *pd = libperf_initialize(-1, -1); /* init lib */ + if (!pd) { + printf("Error initializing libperf\n"); + return -1; + } libperf_enablecounter(pd, LIBPERF_COUNT_HW_INSTRUCTIONS); /* enable HW counter */ From 34fc9afc0a2dc279e5e67fff621e52c9422294b0 Mon Sep 17 00:00:00 2001 From: Mohamad Gebai Date: Mon, 27 Mar 2017 15:44:47 +0200 Subject: [PATCH 4/5] Use fclose instead of close for fdopen() Signed-off-by: Mohamad Gebai --- src/libperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libperf.c b/src/libperf.c index f80ea6f..6d9dabe 100644 --- a/src/libperf.c +++ b/src/libperf.c @@ -216,7 +216,7 @@ libperf_initialize(pid_t pid, int cpu) close: close(fd); - close(pd->log); + fclose(pd->log); for (i = 0; i < nr_counters; i++) { close(pd->fds[i]); } From 0542269d2817b6594d04f1b1f6abadb2ec822bc1 Mon Sep 17 00:00:00 2001 From: Mohamad Gebai Date: Mon, 27 Mar 2017 15:45:06 +0200 Subject: [PATCH 5/5] Update test function to use return value of initialize() Signed-off-by: Mohamad Gebai --- src/libperf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libperf.c b/src/libperf.c index 6d9dabe..bf3e429 100644 --- a/src/libperf.c +++ b/src/libperf.c @@ -334,6 +334,10 @@ libperf_unit_test(void *n) { struct libperf_data *pd = libperf_initialize(0, -1); + if (!pd) { + return -1; + } + char *x = malloc(1024 * 1024 * 1024L); unsigned long int i;