Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fprintf(3) should not be used by signal handlers #638

Open
Sashan opened this issue Oct 5, 2017 · 0 comments
Open

fprintf(3) should not be used by signal handlers #638

Sashan opened this issue Oct 5, 2017 · 0 comments
Assignees
Milestone

Comments

@Sashan
Copy link

Sashan commented Oct 5, 2017

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.

--- a/tcpdump.c 2017-10-05 06:03:58.598362638 -0700
+++ b/tcpdump.c 2017-10-05 05:58:49.245478018 -0700
@@ -165,8 +165,8 @@
 static char *zflag = NULL;             /* compress each savefile using a specified command (like gzip or bzip2) */
 static int immediate_mode;
 
-static int infodelay;
 static int infoprint;
+static int gotalarm;
 
 char *program_name;
 
@@ -1961,7 +1961,9 @@
                setvbuf(stderr, NULL, _IONBF, 0);
 #elif defined(HAVE_ALARM)
                (void)setsignal(SIGALRM, verbose_stats_dump);
-               alarm(1);
+               alarm(1);
+               /* signal alarm to get the first iteration ASAP */
+               gotalarm = 1;
 #endif
        }
 
@@ -2274,8 +2276,6 @@
 
        ++packets_captured;
 
-       ++infodelay;
-
        dump_info = (struct dump_info *)user;
 
        /*
@@ -2464,9 +2464,16 @@
                pcap_dump_flush(dump_info->p);
 #endif
 
-       --infodelay;
-       if (infoprint)
+       if (infoprint) {
                info(0);
+               infoprint = 0;
+       }
+
+       if (gotalarm) {
+               fprintf(stderr, "Got %u\r", packets_captured);
+               gotalarm = 0;
+               alarm(1);
+       }
 }
 
 static void
@@ -2474,8 +2481,6 @@
 {
        ++packets_captured;
 
-       ++infodelay;
-
        pcap_dump(user, h, sp);
 #ifdef HAVE_PCAP_DUMP_FLUSH
        if (Uflag)
@@ -2482,9 +2487,16 @@
                pcap_dump_flush((pcap_dumper_t *)user);
 #endif
 
-       --infodelay;
-       if (infoprint)
+       if (infoprint) {
                info(0);
+               infoprint = 0;
+       }
+
+       if (gotalarm) {
+               fprintf(stderr, "Got %u\r", packets_captured);
+               gotalarm = 0;
+               alarm(1);
+       }
 }
 
 static void
@@ -2492,13 +2504,12 @@
 {
        ++packets_captured;
 
-       ++infodelay;
-
        pretty_print_packet((netdissect_options *)user, h, sp, packets_captured);
 
-       --infodelay;
-       if (infoprint)
+       if (infoprint) {
                info(0);
+               infoprint = 0;
+       }
 }
 
 #ifdef _WIN32
@@ -2531,10 +2542,7 @@
 #ifdef SIGNAL_REQ_INFO
 RETSIGTYPE requestinfo(int signo _U_)
 {
-       if (infodelay)
-               ++infoprint;
-       else
-               info(0);
+       infoprint = 1;
 }
 #endif
 
@@ -2545,15 +2553,12 @@
 void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_,
                                  DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
 {
-       if (infodelay == 0)
-               fprintf(stderr, "Got %u\r", packets_captured);
+       gotalarm = 1;
 }
 #elif defined(HAVE_ALARM)
 static void verbose_stats_dump(int sig _U_)
 {
-       if (infodelay == 0)
-               fprintf(stderr, "Got %u\r", packets_captured);
-       alarm(1);
+       gotalarm = 1;
 }
 #endif

Patch above is against tcpdump-4.9.2. It looks like the signal-safety here prevents tcpdump -w dump.pkt -v to work on Solaris. After applying patch above the issue gets fixed.

I understand proposed solution has some drawback. If there are no packets captured, then nothing gets printed. The ultimate fix calls for much more complex change.

thanks and
regards
sashan

@mcr mcr self-assigned this Apr 16, 2019
@mcr mcr added this to the next_release milestone Apr 16, 2019
Sashan pushed a commit to Sashan/tcpdump that referenced this issue Apr 17, 2019
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:
the-tcpdump-group#638
Sashan pushed a commit to Sashan/tcpdump that referenced this issue Apr 17, 2019
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:
the-tcpdump-group#638
Sashan pushed a commit to Sashan/tcpdump that referenced this issue Apr 18, 2019
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:
the-tcpdump-group#638

(fixes broken build on windows)
Sashan pushed a commit to Sashan/tcpdump that referenced this issue Apr 18, 2019
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:
the-tcpdump-group#638

(fixes broken build on windows)

(s/ifdef/ifndef in my earlier change)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants