Skip to content

Commit

Permalink
refactor: pipe unit test, pipe check usage
Browse files Browse the repository at this point in the history
Signed-off-by: thediveo <thediveo@gmx.eu>
  • Loading branch information
thediveo committed Dec 23, 2023
1 parent ee7ba92 commit f4c8c56
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 24 deletions.
8 changes: 6 additions & 2 deletions capturestream.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,18 @@ func Capture(st csharg.SharkTank) int {
log.Errorf("cannot start capture: %s", err.Error())
return 1
}
defer cs.Stop() // be overly careful

ctx, cancel := context.WithCancel(context.Background())
defer func() {
cancel()
cs.Stop() // be overly careful
}()
// Always keep an eye on the fifo getting closed by Wireshark: we then need
// to stop the capture stream. This is necessary because the capture stream
// might be idle for long times and thus we would otherwise not notice that
// Wireshark has already stopped capturing.
go func() {
pipe.WaitTillBreak(context.Background(), fifo)
pipe.WaitTillBreak(ctx, fifo)
cs.Stop()
}()
// ...and finally wait for the packet capture to terminate (or getting
Expand Down
26 changes: 12 additions & 14 deletions pipe/checker_notwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,38 @@ import (
)

// WaitTillBreak continuously checks a fifo/pipe's producer end (writing end) to
// see when it breaks. When called, WaitTillBreak blocks until the fifo/pipe
// finally has broken. It also returns when the passed context is done.
// see when it breaks. When called, WaitTillBreak blocks until the fifo/named
// pipe finally has “broken”; that is, the reading end has been closed.
// WaitTillBreak also returns when the passed context is done.
//
// This implementation leverages [unix.Poll].
func WaitTillBreak(ctx context.Context, fifo *os.File) {
log.Debug("constantly monitoring packet capture fifo status...")
fifofd, err := unix.Dup(int(fifo.Fd()))
if err != nil {
log.Debugf("cannot duplicate packet capture fifo file descriptor, reason: %s", err.Error())
return
}
defer unix.Close(fifofd)
for {
select {
case <-ctx.Done():
log.Debug("context done while monitoring packet capture fifo")
return
default:
}
// Check the fifo becomming readable, which signals that it has been
// closed. In this case, ex-termi-nate ;) Oh, and remember to correctly
// initialize the fdset each time before calling select() ... well, just
// because that's a good idea to do. :(
fd := fifo.Fd() // n.b. a closed *os.File returns a -1 fd.
if fd == ^uintptr(0) {
log.Debug("stopping packet capture fifo monitoring, as write end has been closed")
return
}
fds := []unix.PollFd{
{
Fd: int32(fd),
Events: 0, // we're interested only in POLLERR and that is ignored here anyway.
Fd: int32(fifofd),
Events: unix.POLLHUP, // we're interested only in POLLERR and that is ignored on input anyway.
},
}
n, err := unix.Poll(fds, 100 /* ms */)
if err != nil {
if err == unix.EINTR {
continue
}
log.Debugf("capture fifo broken, reason: %s", err.Error())
log.Debugf("pipe polling failed, reason: %s", err.Error())
return
}
if n <= 0 {
Expand Down
21 changes: 13 additions & 8 deletions pipe/checker_notwin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,22 @@ var _ = Describe("pipes", func() {
defer os.RemoveAll(tmpfifodir)

fifoname := tmpfifodir + "/fifo"
unix.Mkfifo(fifoname, 0660)
wch := make(chan *os.File)
Expect(unix.Mkfifo(fifoname, 0600)).To(Succeed())

// Open both ends of the named pipe, once for reading and once for
// writing. As this is a rendevouz operation, we run the two open
// operations concurrently and proceed after we've succeeded on both
// ends.
rch := make(chan *os.File)
go func() {
defer GinkgoRecover()
wch <- Successful(os.OpenFile(fifoname, os.O_WRONLY, 0))
rch <- Successful(os.OpenFile(fifoname, os.O_RDONLY, 0))
}()

rch := make(chan *os.File)
wch := make(chan *os.File)
go func() {
defer GinkgoRecover()
rch <- Successful(os.OpenFile(fifoname, os.O_RDONLY, 0))
wch <- Successful(os.OpenFile(fifoname, os.O_WRONLY, 0))
}()

var r, w *os.File
Expand All @@ -59,11 +64,11 @@ var _ = Describe("pipes", func() {

go func() {
defer GinkgoRecover()
By("continously draining the read end of the pipe into /dev/null")
By("continously draining the read end of the pipe into /dev/null...")
null := Successful(os.OpenFile("/dev/null", os.O_WRONLY, 0))
defer null.Close()
io.Copy(null, r)
By("pipe draining done")
By("...pipe draining done")
}()

go func() {
Expand All @@ -75,7 +80,7 @@ var _ = Describe("pipes", func() {

go func() {
defer GinkgoRecover()
time.Sleep(300 * time.Microsecond)
time.Sleep(500 * time.Microsecond)
By("writing some data into the pipe")
w.WriteString("Wireshark rulez")
}()
Expand Down
1 change: 1 addition & 0 deletions pipe/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
)

func TestContainerSharkExtCap(t *testing.T) {
log.SetOutput(GinkgoWriter)
log.SetLevel(log.DebugLevel)

RegisterFailHandler(Fail)
Expand Down

0 comments on commit f4c8c56

Please sign in to comment.