I wrote a simple Python parser for tcpdump. The idea is to continuously run tcpdump as a subprocess, parse its output and output basic reports when the user requests them (by Ctrl-Z interrupts) without stopping the script.
A Ctrl-C should also output the report and totally quit the script, and that works.
The problem is when I press Ctrl-Z, the interrupt handler is called, it outputs tcpdump_output
as expected, but then the script stops processing the output of the tcpdump subprocess, even though it is still running in the background (I checked with ps).
A simplified version of the script:
#!/usr/bin/env python
import subprocess as sub
import socket
import signal
import sys
tcpdump_output = ""
def signal_handler(sig, frame):
print('\nInterrupt detected. Output:')
print(tcpdump_output)
if(sig is signal.SIGINT):
print('Terminated.')
sys.exit(0)
def process_tcpdump_line(line):
print("processing tcpdump line: " + line)
global tcpdump_output
tcpdump_output += line + "\n"
# get host ip address
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
local_ip = s.getsockname()[0]
s.close()
# register interrupt handlers
signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
signal.signal(signal.SIGTSTP, signal_handler) # Handle Ctrl-Z
# prepare tcpdump command
dst = 'dst host ' + local_ip
p = sub.Popen(('sudo', 'tcpdump', '-nqnn', '-l', dst), stdout=sub.PIPE)
# process tcpdump output
for row in iter(p.stdout.readline, b''):
process_tcpdump_line(row.strip())
print("this is never reached.")
I tried wrapping the for-loop in a while True
but when debugging I see that it doesn't make a difference, the last line is really never reached.
So seems like after the handled interrupt, the script hangs on p.stdout.readline
.
Is there a way to handle the interrupt without affecting the subprocess, or otherwise resume its processing?