From 183df8f29eb85d159b15a88ce106c6bdcf0add69 Mon Sep 17 00:00:00 2001 From: alexandr nedvedicky - Sun Microsystems - Prague Czech Republic Date: Wed, 17 Apr 2019 09:44:24 +0200 Subject: [PATCH] fprintf(3) should not be used by signal handlers On most OS platforms fprintf() et.al. are considered to be signal unsafe. I've noticed the signal handlers in tcpdump call fprintf(). The patch below defers call to fprintf() triggered by signal to pcap_loop callback. Submitted to upstream: https://github.com/the-tcpdump-group/tcpdump/issues/638 --- tcpdump.c | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/tcpdump.c b/tcpdump.c index 52af74af5f..1d27f2eb69 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -217,8 +217,8 @@ static char *zflag = NULL; /* compress each savefile using a specified command static int immediate_mode; #endif -static int infodelay; static int infoprint; +static int gotalarm; char *program_name; @@ -2387,6 +2387,9 @@ DIAG_ON_CLANG(assign-enum) */ struct itimerval timer; (void)setsignal(SIGALRM, verbose_stats_dump); + alarm(1); + /* signal alarm to get the first iteration ASAP */ + gotalarm = 1; timer.it_interval.tv_sec = 1; timer.it_interval.tv_usec = 0; timer.it_value.tv_sec = 1; @@ -2738,8 +2741,6 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s ++packets_captured; - ++infodelay; - dump_info = (struct dump_info *)user; /* @@ -2941,9 +2942,16 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s if (dump_info->ndo != NULL) pretty_print_packet(dump_info->ndo, h, sp, packets_captured); - --infodelay; - if (infoprint) + if (infoprint) { info(0); + infoprint = 0; + } + + if (gotalarm) { + fprintf(stderr, "Got %u\r", packets_captured); + gotalarm = 0; + alarm(1); + } } static void @@ -2953,8 +2961,6 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ++packets_captured; - ++infodelay; - dump_info = (struct dump_info *)user; pcap_dump((u_char *)dump_info->pdd, h, sp); @@ -2966,9 +2972,10 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) if (dump_info->ndo != NULL) pretty_print_packet(dump_info->ndo, h, sp, packets_captured); - --infodelay; - if (infoprint) + if (infoprint) { info(0); + infoprint = 0; + } } static void @@ -2976,23 +2983,25 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { ++packets_captured; - ++infodelay; - pretty_print_packet((netdissect_options *)user, h, sp, packets_captured); - --infodelay; - if (infoprint) + if (infoprint) { info(0); + infoprint = 0; + } + + if (gotalarm) { + fprintf(stderr, "Got %u\r", packets_captured); + gotalarm = 0; + alarm(1); + } } #ifdef SIGNAL_REQ_INFO static void requestinfo(int signo _U_) { - if (infodelay) - ++infoprint; - else - info(0); + infoprint = 1; } #endif @@ -3010,7 +3019,7 @@ print_packets_captured (void) { static u_int prev_packets_captured, first = 1; - if (infodelay == 0 && (first || packets_captured != prev_packets_captured)) { + if (first || packets_captured != prev_packets_captured) { fprintf(stderr, "Got %u\r", packets_captured); first = 0; prev_packets_captured = packets_captured; @@ -3024,12 +3033,12 @@ print_packets_captured (void) static void CALLBACK verbose_stats_dump(PVOID param _U_, BOOLEAN timer_fired _U_) { - print_packets_captured(); + gotalarm = 1; } #else /* _WIN32 */ static void verbose_stats_dump(int sig _U_) { - print_packets_captured(); + gotalarm = 1; } #endif /* _WIN32 */