libbpf-tools: fix EINTR related issues
authorMauricio Vásquez <mauricio@kinvolk.io>
Fri, 17 Sep 2021 14:40:41 +0000 (09:40 -0500)
committerMauricio Vásquez <mauricio@kinvolk.io>
Fri, 24 Sep 2021 12:11:05 +0000 (07:11 -0500)
1. Most of the tools that use perf_buffer__poll() were not handling the
case when it was interrupted by a signal, they were just ending.
We noticed this issue by running the tools inside a container, after
some seconds they will finish:

```
$ time /execsnoop
...
runc             210198 939      0 /usr/sbin/runc --version
docker-init      210205 939      0 /usr/bin/docker-init --version
Error polling perf buffer: -4

real 0m48.913s
user 0m0.020s
sys 0m0.033s
```

This commit fixes that by checking if errno is EINTR after calling
perf_buffer__poll().

2. Many tools were returning non zero when ended by SIG_INT.

```
$ sudo ./execsnoop
PCOMM            PID    PPID   RET ARGS
runc             203967 939      0 /usr/sbin/runc --version
docker-init      203973 939      0 /usr/bin/docker-init --version
calico           203974 724      0 /opt/cni/bin/calico
portmap          203985 724      0 /opt/cni/bin/portmap
bandwidth        203990 724      0 /opt/cni/bin/bandwidth
^C
$ echo $?
130
```

3. Some tools were missing the SIG_INT handler

Signed-off-by: Mauricio Vásquez <mauricio@kinvolk.io>
17 files changed:
libbpf-tools/bindsnoop.c
libbpf-tools/biosnoop.c
libbpf-tools/drsnoop.c
libbpf-tools/execsnoop.c
libbpf-tools/exitsnoop.c
libbpf-tools/filelife.c
libbpf-tools/filetop.c
libbpf-tools/fsslower.c
libbpf-tools/gethostlatency.c
libbpf-tools/ksnoop.c
libbpf-tools/mountsnoop.c
libbpf-tools/opensnoop.c
libbpf-tools/runqslower.c
libbpf-tools/solisten.c
libbpf-tools/statsnoop.c
libbpf-tools/tcpconnect.c
libbpf-tools/tcpconnlat.c

index 05bbd3f..8e0aadc 100644 (file)
@@ -222,7 +222,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
@@ -231,15 +232,18 @@ int main(int argc, char **argv)
        printf("%-7s %-16s %-3s %-5s %-5s %-4s %-5s %-48s\n",
               "PID", "COMM", "RET", "PROTO", "OPTS", "IF", "PORT", "ADDR");
 
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
-               if (exiting)
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       warn("error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("error polling perf buffer: %d\n", err);
 
 cleanup:
+       perf_buffer__free(pb);
        bindsnoop_bpf__destroy(obj);
 
        return err != 0;
index 42a9a06..e0f0069 100644 (file)
@@ -4,6 +4,7 @@
 // Based on biosnoop(8) from BCC by Brendan Gregg.
 // 29-Jun-2020   Wenbo Zhang   Created this.
 #include <argp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <time.h>
@@ -18,6 +19,8 @@
 #define PERF_BUFFER_PAGES      16
 #define PERF_POLL_TIMEOUT_MS   100
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct env {
        char *disk;
        int duration;
@@ -98,6 +101,11 @@ int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 static void blk_fill_rwbs(char *rwbs, unsigned int op)
 {
        int i = 0;
@@ -293,16 +301,27 @@ int main(int argc, char **argv)
        if (env.duration)
                time_end = get_ktime_ns() + env.duration * NSEC_PER_SEC;
 
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
        /* main: poll */
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
                if (env.duration && get_ktime_ns() > time_end)
                        goto cleanup;
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       printf("error polling perf buffer: %d\n", err);
 
 cleanup:
+       perf_buffer__free(pb);
        biosnoop_bpf__destroy(obj);
        ksyms__free(ksyms);
        partitions__free(partitions);
index 3bb827f..2b0290c 100644 (file)
@@ -4,6 +4,7 @@
 // Based on drsnoop(8) from BCC by Wenbo Zhang.
 // 28-Feb-2020   Wenbo Zhang   Created this.
 #include <argp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -18,6 +19,8 @@
 #define PERF_BUFFER_PAGES      16
 #define PERF_POLL_TIMEOUT_MS   100
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct env {
        pid_t pid;
        pid_t tid;
@@ -109,6 +112,11 @@ int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
 {
        const struct event *e = data;
@@ -221,14 +229,24 @@ int main(int argc, char **argv)
        if (env.duration)
                time_end = get_ktime_ns() + env.duration * NSEC_PER_SEC;
 
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
        /* main: poll */
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
                if (env.duration && get_ktime_ns() > time_end)
                        goto cleanup;
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       printf("error polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 1c89897..1a93af0 100644 (file)
@@ -1,6 +1,7 @@
 // Based on execsnoop(8) from BCC by Brendan Gregg and others.
 //
 #include <argp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "trace_helpers.h"
 
 #define PERF_BUFFER_PAGES   64
+#define PERF_POLL_TIMEOUT_MS   100
 #define NSEC_PRECISION (NSEC_PER_SEC / 1000)
 #define MAX_ARGS_KEY 259
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct env {
        bool time;
        bool timestamp;
@@ -137,6 +141,11 @@ static int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 static void time_since_start()
 {
        long nsec, sec;
@@ -319,10 +328,22 @@ int main(int argc, char **argv)
                goto cleanup;
        }
 
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
        /* main: poll */
-       while ((err = perf_buffer__poll(pb, 100)) >= 0)
-               ;
-       printf("Error polling perf buffer: %d\n", err);
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
+       }
 
 cleanup:
        perf_buffer__free(pb);
index 8ef8584..6556bb1 100644 (file)
@@ -187,7 +187,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
@@ -196,19 +197,15 @@ int main(int argc, char **argv)
        printf("%-16s %-7s %-7s %-7s %-7s %-s\n",
               "PCOMM", "PID", "PPID", "TID", "AGE(s)", "EXIT_CODE");
 
-       while (1) {
+       while (!exiting) {
                err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
-               if (err == -EINTR) {
-                       err = 0;
-                       goto cleanup;
-               }
-
-               if (err < 0)
-                       break;
-               if (exiting)
+               if (err < 0 && errno != EINTR) {
+                       warn("error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("error polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 4c45a2c..ecca5b2 100644 (file)
@@ -4,6 +4,7 @@
 // Based on filelife(8) from BCC by Brendan Gregg & Allan McAleavy.
 // 20-Mar-2020   Wenbo Zhang   Created this.
 #include <argp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -18,6 +19,8 @@
 #define PERF_BUFFER_PAGES      16
 #define PERF_POLL_TIMEOUT_MS   100
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct env {
        pid_t pid;
        bool verbose;
@@ -76,6 +79,11 @@ int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
 {
        const struct event *e = data;
@@ -155,9 +163,21 @@ int main(int argc, char **argv)
                goto cleanup;
        }
 
-       while ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) >= 0)
-               ;
-       fprintf(stderr, "error polling perf buffer: %d\n", err);
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
+       }
 
 cleanup:
        perf_buffer__free(pb);
index e7fb74d..90a15ee 100644 (file)
@@ -284,7 +284,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
index 6ffefef..7e56fac 100644 (file)
@@ -76,7 +76,7 @@ static char file_op[] = {
        [FSYNC] = 'F',
 };
 
-static volatile sig_atomic_t exiting;
+static volatile sig_atomic_t exiting = 0;
 
 /* options */
 static enum fs_type fs_type = NONE;
@@ -188,7 +188,7 @@ static int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
-static void sig_handler(int sig)
+static void sig_int(int signo)
 {
        exiting = 1;
 }
@@ -429,8 +429,6 @@ int main(int argc, char **argv)
                goto cleanup;
        }
 
-       signal(SIGINT, sig_handler);
-
        pb_opts.sample_cb = handle_event;
        pb_opts.lost_cb = handle_lost_events;
        pb = perf_buffer__new(bpf_map__fd(skel->maps.events), PERF_BUFFER_PAGES,
@@ -447,13 +445,24 @@ int main(int argc, char **argv)
        if (duration)
                time_end = get_ktime_ns() + duration * NSEC_PER_SEC;
 
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
+       /* main: poll */
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
                if (duration && get_ktime_ns() > time_end)
                        goto cleanup;
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("failed with polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 4b57d0e..3485981 100644 (file)
@@ -25,6 +25,7 @@
 #define warn(...) fprintf(stderr, __VA_ARGS__)
 
 static volatile sig_atomic_t exiting = 0;
+
 static pid_t target_pid = 0;
 static const char *libc_path = NULL;
 
@@ -264,20 +265,23 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
        printf("%-8s %-7s %-16s %-10s %-s\n",
               "TIME", "PID", "COMM", "LATms", "HOST");
 
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
-               if (exiting)
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       warn("error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("error polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 29f6fcd..22b5ef0 100644 (file)
@@ -4,6 +4,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <getopt.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -19,6 +20,8 @@
 #define KSNOOP_VERSION "0.1"
 #endif
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct btf *vmlinux_btf;
 static const char *bin_name;
 static int pages = PAGES_DEFAULT;
@@ -773,6 +776,11 @@ static void lost_handler(void *ctx, int cpu, __u64 cnt)
        p_err("\t/* lost %llu events */", cnt);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 static int add_traces(struct bpf_map *func_map, struct trace *traces,
                      int nr_traces)
 {
@@ -886,14 +894,23 @@ static int cmd_trace(int argc, char **argv)
 
        printf("%16s %4s %8s %s\n", "TIME", "CPU", "PID", "FUNCTION/ARGS");
 
-       while (1) {
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               ret = 1;
+               goto cleanup;
+       }
+
+       while (!exiting) {
                ret = perf_buffer__poll(pb, 1);
-               if (ret < 0 && ret != -EINTR) {
-                       p_err("Polling failed: %s", strerror(-ret));
-                       break;
+               if (ret < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
                }
+               /* reset ret to return 0 if exiting */
+               ret = 0;
        }
 
+cleanup:
        perf_buffer__free(pb);
        ksnoop_bpf__destroy(skel);
 
index ff041ef..49f4e16 100644 (file)
@@ -282,7 +282,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
@@ -292,13 +293,15 @@ int main(int argc, char **argv)
                printf("%-16s %-7s %-7s %-11s %s\n", "COMM", "PID", "TID", "MNT_NS", "CALL");
        }
 
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
-               if (exiting)
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("error polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 947d14f..935db66 100644 (file)
@@ -5,6 +5,7 @@
 // Based on opensnoop(8) from BCC by Brendan Gregg and others.
 // 14-Feb-2020   Brendan Gregg   Created this.
 #include <argp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,6 +29,8 @@
 
 #define NSEC_PER_SEC           1000000000ULL
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct env {
        pid_t pid;
        pid_t tid;
@@ -165,6 +168,11 @@ int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
 {
        const struct event *e = data;
@@ -290,15 +298,24 @@ int main(int argc, char **argv)
        if (env.duration)
                time_end = get_ktime_ns() + env.duration * NSEC_PER_SEC;
 
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
        /* main: poll */
-       while (1) {
-               usleep(PERF_BUFFER_TIME_MS * 1000);
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
                if (env.duration && get_ktime_ns() > time_end)
                        goto cleanup;
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       printf("Error polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 3d518ac..bd96258 100644 (file)
@@ -4,6 +4,7 @@
 // Based on runqslower(8) from BCC by Ivan Babrou.
 // 11-Feb-2020   Andrii Nakryiko   Created this.
 #include <argp.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -14,6 +15,8 @@
 #include "runqslower.skel.h"
 #include "trace_helpers.h"
 
+static volatile sig_atomic_t exiting = 0;
+
 struct env {
        pid_t pid;
        pid_t tid;
@@ -110,6 +113,11 @@ int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
 {
        const struct event *e = data;
@@ -194,9 +202,21 @@ int main(int argc, char **argv)
                goto cleanup;
        }
 
-       while ((err = perf_buffer__poll(pb, 100)) >= 0)
-               ;
-       printf("Error polling perf buffer: %d\n", err);
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
+       while (!exiting) {
+               err = perf_buffer__poll(pb, 100);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
+       }
 
 cleanup:
        perf_buffer__free(pb);
index b5f68a6..a2d4027 100644 (file)
@@ -177,7 +177,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
@@ -186,13 +187,15 @@ int main(int argc, char **argv)
        printf("%-7s %-16s %-3s %-7s %-5s %-5s %-32s\n",
               "PID", "COMM", "RET", "BACKLOG", "PROTO", "PORT", "ADDR");
 
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
-               if (exiting)
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       warn("error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("error polling perf buffer: %d\n", err);
 
 cleanup:
        perf_buffer__free(pb);
index 3ec6ac2..5853997 100644 (file)
@@ -162,7 +162,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
@@ -171,15 +172,18 @@ int main(int argc, char **argv)
        printf("%-7s %-20s %-4s %-4s %-s\n",
               "PID", "COMM", "RET", "ERR", "PATH");
 
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
-               if (exiting)
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       warn("error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       warn("error polling perf buffer: %d\n", err);
 
 cleanup:
+       perf_buffer__free(pb);
        statsnoop_bpf__destroy(obj);
 
        return err != 0;
index d71f981..72448a8 100644 (file)
@@ -17,6 +17,8 @@
 
 #define warn(...) fprintf(stderr, __VA_ARGS__)
 
+static volatile sig_atomic_t exiting = 0;
+
 const char *argp_program_version = "tcpconnect 0.1";
 const char *argp_program_bug_address =
        "https://github.com/iovisor/bcc/tree/master/libbpf-tools";
@@ -192,11 +194,9 @@ static int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
-static volatile sig_atomic_t hang_on = 1;
-
 static void sig_int(int signo)
 {
-       hang_on = 0;
+       exiting = 1;
 }
 
 static void print_count_ipv4(int map_fd)
@@ -261,7 +261,7 @@ static void print_count(int map_fd_ipv4, int map_fd_ipv6)
 {
        static const char *header_fmt = "\n%-25s %-25s %-20s %-10s\n";
 
-       while (hang_on)
+       while (!exiting)
                pause();
 
        printf(header_fmt, "LADDR", "RADDR", "RPORT", "CONNECTS");
@@ -341,12 +341,14 @@ static void print_events(int perf_map_fd)
        }
 
        print_events_header();
-       while (hang_on) {
+       while (!exiting) {
                err = perf_buffer__poll(pb, 100);
                if (err < 0 && errno != EINTR) {
-                       warn("Error polling perf buffer: %d\n", err);
+                       warn("error polling perf buffer: %s\n", strerror(errno));
                        goto cleanup;
                }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
 
 cleanup:
@@ -408,7 +410,8 @@ int main(int argc, char **argv)
        }
 
        if (signal(SIGINT, sig_int) == SIG_ERR) {
-               warn("can't set signal handler: %s\n", strerror(-errno));
+               warn("can't set signal handler: %s\n", strerror(errno));
+               err = 1;
                goto cleanup;
        }
 
index 7cd7461..3e06447 100644 (file)
@@ -5,6 +5,7 @@
 // 11-Jul-2020   Wenbo Zhang   Created this.
 #include <argp.h>
 #include <arpa/inet.h>
+#include <signal.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <time.h>
@@ -17,6 +18,8 @@
 #define PERF_BUFFER_PAGES      16
 #define PERF_POLL_TIMEOUT_MS   100
 
+static volatile sig_atomic_t exiting = 0;
+
 static struct env {
        __u64 min_us;
        pid_t pid;
@@ -96,6 +99,11 @@ int libbpf_print_fn(enum libbpf_print_level level,
        return vfprintf(stderr, format, args);
 }
 
+static void sig_int(int signo)
+{
+       exiting = 1;
+}
+
 void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
 {
        const struct event *e = data;
@@ -196,14 +204,25 @@ int main(int argc, char **argv)
        printf("%-6s %-12s %-2s %-16s %-16s %-5s %s\n",
                "PID", "COMM", "IP", "SADDR", "DADDR", "DPORT", "LAT(ms)");
 
+       if (signal(SIGINT, sig_int) == SIG_ERR) {
+               fprintf(stderr, "can't set signal handler: %s\n", strerror(errno));
+               err = 1;
+               goto cleanup;
+       }
+
        /* main: poll */
-       while (1) {
-               if ((err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS)) < 0)
-                       break;
+       while (!exiting) {
+               err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);
+               if (err < 0 && errno != EINTR) {
+                       fprintf(stderr, "error polling perf buffer: %s\n", strerror(errno));
+                       goto cleanup;
+               }
+               /* reset err to return 0 if exiting */
+               err = 0;
        }
-       printf("error polling perf buffer: %d\n", err);
 
 cleanup:
+       perf_buffer__free(pb);
        tcpconnlat_bpf__destroy(obj);
 
        return err != 0;