From 806de4ac9441f268ae7af8e50d4c14dacba06168 Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Tue, 19 May 2020 01:48:55 -0400 Subject: [PATCH] portlist: fix "readdirent: no such file or directory" errors on Linux. This could happen when a process disappeared while we were reading its file descriptor list. I was able to replicate the problem by running this in another terminal: while :; do for i in $(seq 10); do /bin/true & done >&/dev/null; wait >&/dev/null; done And then running the portlist tests thousands of times. Fixes #339. Signed-off-by: Avery Pennarun --- portlist/portlist_linux.go | 12 ++++++++++++ portlist/portlist_test.go | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/portlist/portlist_linux.go b/portlist/portlist_linux.go index d8756c253..abdc134ff 100644 --- a/portlist/portlist_linux.go +++ b/portlist/portlist_linux.go @@ -110,6 +110,12 @@ func addProcesses(pl []Port) ([]Port, error) { if err == io.EOF { return nil } + if os.IsNotExist(err) { + // This can happen if the directory we're + // reading disappears during the run. No big + // deal. + return nil + } if err != nil { return fmt.Errorf("addProcesses.readDir: %w", err) } @@ -155,6 +161,12 @@ func foreachPID(fn func(pidStr string) error) error { if err == io.EOF { return nil } + if os.IsNotExist(err) { + // This can happen if the directory we're + // reading disappears during the run. No big + // deal. + return nil + } if err != nil { return fmt.Errorf("foreachPID.readdir: %w", err) } diff --git a/portlist/portlist_test.go b/portlist/portlist_test.go index 2e1f4a88a..64613f68c 100644 --- a/portlist/portlist_test.go +++ b/portlist/portlist_test.go @@ -7,9 +7,14 @@ package portlist import ( "net" "testing" + + "tailscale.com/tstest" ) func TestGetList(t *testing.T) { + rc := tstest.NewResourceCheck() + defer rc.Assert(t) + pl, err := GetList(nil) if err != nil { t.Fatal(err) @@ -21,6 +26,9 @@ func TestGetList(t *testing.T) { } func TestIgnoreLocallyBoundPorts(t *testing.T) { + rc := tstest.NewResourceCheck() + defer rc.Assert(t) + ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Skipf("failed to bind: %v", err)