Zombie tcpdump Process After Using sniff() on pcap with Filter
Brief description
When using Scapy's sniff() function to read from a pcap file, a zombie tcpdump process is left behind if the filter argument is set to a non-None value. This issue occurs consistently when a BPF filter is applied during packet sniffing, leading to potential resource leakage and system instability due to the accumulation of zombie processes.
Scapy version
2.5
Python version
3.11
Operating system
Linux Debian 6.1.99-1
Additional environment information
No response
How to reproduce
- Start scapy interactive console
- Call
sniff(offline="/path/to/any.pcap", filter="") - In another terminal execute
ps x | grep tcpdump
Actual result
The ps command lists the tcpdump process with a <defunct> status, indicating that the process has become a zombie. This status means the process has completed execution but remains in the process table because its parent process has not yet read its exit status.
Expected result
ps should not show any tcpdump processes if sniff is done reading the pcap file
Related resources
No response
Thanks for this report. You're right. Also, Python reports this (at least Python 3.12):
/usr/lib/python3.12/subprocess.py:1127: ResourceWarning: subprocess 123456 is still running
_warn("subprocess %s is still running" % self.pid,
ResourceWarning: Enable tracemalloc to get the object allocation traceback
An option to patch this would be to prevent tcpdump() from being used with getfd=True without using a with pattern.
@p-l- Here are few of my observations about your suggestion of using with pattern:
- Calling
tcpdumpwithgetfd=Truereturns us aPopen.stdout. - Using
withonPopen.stdoutcloses the stdout pipe when its context ends, but the Popen object still exists for the tcpdump subprocess.
Few ways we can handle this:
- Straight out just refrain from using
tcpdump()in the sniffer when we have a falsy value offltinstead of just validatingfltagainstNone. - Instead of using
getfd=Truein tcpdump inside the sniffer, we usegetproc=Truewhich provides the sniffer with the tcpdump Popen object, which we can then use alongwithto properly close the tcpdump's Popen object when its context ends.
Please let me know which of these fixes make the most sense to implement and I will create a PR with the fix.
Thanks !