summaryrefslogtreecommitdiffhomepage
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/tailscaled/tailscaled.go14
-rw-r--r--cmd/tailscaled/tailscaled_windows.go41
2 files changed, 36 insertions, 19 deletions
diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go
index bab3bc75a..2a1adefe4 100644
--- a/cmd/tailscaled/tailscaled.go
+++ b/cmd/tailscaled/tailscaled.go
@@ -59,6 +59,7 @@ import (
"tailscale.com/tsd"
"tailscale.com/tsweb/varz"
"tailscale.com/types/flagtype"
+ "tailscale.com/types/lazy"
"tailscale.com/types/logger"
"tailscale.com/types/logid"
"tailscale.com/util/clientmetric"
@@ -153,6 +154,14 @@ var subCommands = map[string]*func([]string) error{
var beCLI func() // non-nil if CLI is linked in
+// tailscaledInit facilitates the lazy initialization of tailscaled.
+// It defers potentially expensive and platform-specific
+// initialization steps until the main function is called and
+// determines that the current process is an actual tailscaled
+// process, rather than a CLI symlink, `tailscaled --version`, or
+// another subcommand that doesn't require full initialization.
+var tailscaledInit lazy.DeferredInit
+
func main() {
envknob.PanicIfAnyEnvCheckedInInit()
envknob.ApplyDiskConfig()
@@ -227,6 +236,11 @@ func main() {
log.Fatalf("--bird-socket is not supported on %s", runtime.GOOS)
}
+ if err := tailscaledInit.Do(); err != nil {
+ log.SetFlags(0)
+ log.Fatalf("tailscaled init failed: %v", err)
+ }
+
// Only apply a default statepath when neither have been provided, so that a
// user may specify only --statedir if they wish.
if args.statepath == "" && args.statedir == "" {
diff --git a/cmd/tailscaled/tailscaled_windows.go b/cmd/tailscaled/tailscaled_windows.go
index 7208e03da..d291415c8 100644
--- a/cmd/tailscaled/tailscaled_windows.go
+++ b/cmd/tailscaled/tailscaled_windows.go
@@ -60,31 +60,34 @@ import (
"tailscale.com/wf"
)
-func init() {
- // Initialize COM process-wide.
- comProcessType := com.Service
- if !isWindowsService() {
- comProcessType = com.ConsoleApp
- }
- if err := com.StartRuntime(comProcessType); err != nil {
- log.Printf("wingoes.com.StartRuntime(%d) failed: %v", comProcessType, err)
- }
-}
-
// permitPolicyLocks is a function to be called to lift the restriction on acquiring
// [gp.PolicyLock]s once the service is running.
// It is safe to be called multiple times.
var permitPolicyLocks = func() {}
func init() {
- if isWindowsService() {
- // We prevent [gp.PolicyLock]s from being acquired until the service enters the running state.
- // Otherwise, if tailscaled starts due to a GPSI policy installing Tailscale, it may deadlock
- // while waiting for the write counterpart of the GP lock to be released by Group Policy,
- // which is itself waiting for the installation to complete and tailscaled to start.
- // See tailscale/tailscale#14416 for more information.
- permitPolicyLocks = gp.RestrictPolicyLocks()
- }
+ tailscaledInit.Defer(func() error {
+ // Initialize COM process-wide.
+ comProcessType := com.Service
+ isService := isWindowsService()
+ if !isService {
+ comProcessType = com.ConsoleApp
+ }
+ if err := com.StartRuntime(comProcessType); err != nil {
+ return errors.New(fmt.Sprintf("wingoes.com.StartRuntime(%d) failed: %v", comProcessType, err))
+ }
+
+ if isService {
+ // We prevent [gp.PolicyLock]s from being acquired until the service enters the running state.
+ // Otherwise, if tailscaled starts due to a GPSI policy installing Tailscale, it may deadlock
+ // while waiting for the write counterpart of the GP lock to be released by Group Policy,
+ // which is itself waiting for the installation to complete and tailscaled to start.
+ // See tailscale/tailscale#14416 for more information.
+ permitPolicyLocks = gp.RestrictPolicyLocks()
+ }
+
+ return nil
+ })
}
const serviceName = "Tailscale"