Skip to content

Conversation

@schaap
Copy link

@schaap schaap commented Feb 9, 2026

When starting an AsyncSniffer, one can provide a started_callback which is called when the sniffer starts sniffing. After this callback has been called it can reasonably be assumed that the sniffer is indeed running and hence can be stopped.

We have existing automated tests using AsyncSniffer via a wrapping context manager, for convenience of writing those tests: when entering the context the sniffer is started and when leaving the context again the sniffer is stopped. The context manager waits until the callback is called before finishing its __enter__, with the callback signalling a Barrier to inform the context manager about this.

In particularly short tests, which almost immediately close the sniffer again, it turned out that this can cause the sniffer to hang or exceptions to be raised. This happens when the following events occurs, in this very order:

  1. Our callback is called by the AsyncSniffer
  2. Our callback signals the context manager
  3. The context manager yields to the calling test
  4. The test immediately decides to leave the context again
  5. The context manager stops the AsyncSniffer
  6. The AsyncSniffer thread sets self.continue_sniff to True

Note the thread switches: steps 1, 2 and 6 execute on the AsyncSniffer thread, steps 3 through 5 on the test's primary thread.

We can hit this race condition with fair reproducibility (tens of percents - no exact numbers known). Calling started_callback only after setting self.continue_sniff makes this entirely stable.

I have not included a test for this, as it is impossible hit this race condition anywhere near reliably (we have exacerbating conditions in our particular setup).

@polybassa
Copy link
Contributor

Thanks for the PR.

@codecov
Copy link

codecov bot commented Feb 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.10%. Comparing base (ded1d73) to head (d87e445).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4912      +/-   ##
==========================================
- Coverage   80.10%   80.10%   -0.01%     
==========================================
  Files         370      370              
  Lines       91727    91727              
==========================================
- Hits        73477    73476       -1     
- Misses      18250    18251       +1     
Files with missing lines Coverage Δ
scapy/sendrecv.py 86.49% <100.00%> (ø)

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants