From 9687f3700d88d58544f7be26a9324dc2b5a0abca Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Mon, 6 Mar 2023 15:54:08 -0700 Subject: [PATCH] net/dns: deal with Windows wsl.exe hangs Despite the fact that WSL configuration is still disabled by default, we continue to log the machine's list of WSL distros as a diagnostic measure. Unfortunately I have seen the "wsl.exe -l" command hang indefinitely. This patch adds a (more than reasonable) 10s timeout to ensure that tailscaled does not get stuck while executing this operation. I also modified the Windows implementation of NewOSConfigurator to do the logging asynchronously, since that information is not required in order to continue starting up. Fixes #7476 Signed-off-by: Aaron Klotz --- net/dns/manager_windows.go | 14 ++++++++------ net/dns/wsl_windows.go | 10 +++++++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/net/dns/manager_windows.go b/net/dns/manager_windows.go index 56ab32f45..4c05b7718 100644 --- a/net/dns/manager_windows.go +++ b/net/dns/manager_windows.go @@ -51,12 +51,14 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, ret.nrptDB = newNRPTRuleDatabase(logf) } - // Log WSL status once at startup. - if distros, err := wslDistros(); err != nil { - logf("WSL: could not list distributions: %v", err) - } else { - logf("WSL: found %d distributions", len(distros)) - } + go func() { + // Log WSL status once at startup. + if distros, err := wslDistros(); err != nil { + logf("WSL: could not list distributions: %v", err) + } else { + logf("WSL: found %d distributions", len(distros)) + } + }() return ret, nil } diff --git a/net/dns/wsl_windows.go b/net/dns/wsl_windows.go index 8990fdcc7..90632ce5f 100644 --- a/net/dns/wsl_windows.go +++ b/net/dns/wsl_windows.go @@ -5,6 +5,7 @@ package dns import ( "bytes" + "context" "errors" "fmt" "os" @@ -12,6 +13,7 @@ import ( "os/user" "strings" "syscall" + "time" "golang.org/x/sys/windows" "tailscale.com/types/logger" @@ -20,7 +22,13 @@ import ( // wslDistros reports the names of the installed WSL2 linux distributions. func wslDistros() ([]string, error) { - b, err := wslCombinedOutput(exec.Command("wsl.exe", "-l")) + // There is a bug in some builds of wsl.exe that causes it to block + // indefinitely while executing this operation. Set a timeout so that we don't + // get wedged! (Issue #7476) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + b, err := wslCombinedOutput(exec.CommandContext(ctx, "wsl.exe", "-l")) if err != nil { return nil, fmt.Errorf("%v: %q", err, string(b)) }