Allow to cancel the PacketSource.Packets() underlying Goroutine
- Dominant language
- Go
- Stars
- 6.8k
- Forks
- 1.2k
- PR merge metrics
- No merged PRs in 30d
Description
While working on [gitlab.com/inetmock/inetmock](https://gitlab.com/inetmock/inetmock) and making sure I don't have any race conditions I noticed some edge cases with gopacket's `EthernetHandle` and `PacketSource`.
Similar to issue #890 I wanted to stop the PCAP recording while the process continues. Therefore I'm closing the `EthernetHandle`. While this seems to work, the `-race` switch detects a problem because the underlying Goroutine of the `PacketSource.Packets()` call continues to use the file descriptor for the socket while the `Close() error` function closes the handle because `Close() error` does not lock the `EthernetHandle` instance.
Furthermore the `SYS_RECVMSG` syscall blocks if the `MSG_DONTWAIT` flag is not used which blocks the Goroutine from `PacketSource.Packets()` even if it has a `context.Context` to check if it shall continue the routine isn't returning and therefore not closing the upstream channel.
I prepared a patch to:
* lock the `EthernetHandle` instance while closing the file descriptor
* check in `EthernetHandle` if the underlying handle got closed and return an `io.EOF` error (this also stops the `PacketSource.Packets()` call)
* add `MSG_DONTWAIT` flag to the syscall to return if the handle got closed
* add an `PacketSource.PacketsCtx(ctx context.Context)` overload to allow cancellation of the underlying Goroutine by not breaking the current behavior by submitting a `context.Background()` in the original function
* replace `err == ...` calls with the Go 1.13 `errors.Is(...)` function to improve the error checking
* add some tests to make sure everything works as expected and to show how it works
Contributor guide
Assessment
This issue has not been assessed yet.