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 <aaron@tailscale.com>
This commit is contained in:
Aaron Klotz 2023-03-06 15:54:08 -07:00
parent 2263d9c44b
commit 9687f3700d
2 changed files with 17 additions and 7 deletions

View File

@ -51,12 +51,14 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator,
ret.nrptDB = newNRPTRuleDatabase(logf) ret.nrptDB = newNRPTRuleDatabase(logf)
} }
// Log WSL status once at startup. go func() {
if distros, err := wslDistros(); err != nil { // Log WSL status once at startup.
logf("WSL: could not list distributions: %v", err) if distros, err := wslDistros(); err != nil {
} else { logf("WSL: could not list distributions: %v", err)
logf("WSL: found %d distributions", len(distros)) } else {
} logf("WSL: found %d distributions", len(distros))
}
}()
return ret, nil return ret, nil
} }

View File

@ -5,6 +5,7 @@
import ( import (
"bytes" "bytes"
"context"
"errors" "errors"
"fmt" "fmt"
"os" "os"
@ -12,6 +13,7 @@
"os/user" "os/user"
"strings" "strings"
"syscall" "syscall"
"time"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"tailscale.com/types/logger" "tailscale.com/types/logger"
@ -20,7 +22,13 @@
// wslDistros reports the names of the installed WSL2 linux distributions. // wslDistros reports the names of the installed WSL2 linux distributions.
func wslDistros() ([]string, error) { 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 { if err != nil {
return nil, fmt.Errorf("%v: %q", err, string(b)) return nil, fmt.Errorf("%v: %q", err, string(b))
} }