Skip to content

Commit

Permalink
fprintf(3) should not be used by signal handlers
Browse files Browse the repository at this point in the history
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
  • Loading branch information
alexandr nedvedicky - Sun Microsystems - Prague Czech Republic committed Apr 17, 2019
1 parent de250d5 commit 183df8f
Showing 1 changed file with 29 additions and 20 deletions.
49 changes: 29 additions & 20 deletions tcpdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

/*
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -2966,33 +2972,36 @@ 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
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

Expand All @@ -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;
Expand All @@ -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 */

Expand Down

0 comments on commit 183df8f

Please sign in to comment.