diff --git a/core/events.go b/core/events.go index 5bc36504..8971dc8a 100644 --- a/core/events.go +++ b/core/events.go @@ -43,8 +43,6 @@ func shutdown(ctx context.Context, _ interface{}) error { // restart restarts the Portmaster. func restart(ctx context.Context, data interface{}) error { log.Info("core: user requested restart") - modules.SetExitStatusCode(updates.RestartExitCode) - // Do not use a worker, as this would block itself here. - go modules.Shutdown() //nolint:errcheck + updates.RestartNow() return nil } diff --git a/updates/restart.go b/updates/restart.go index 551191bf..a6d5a34d 100644 --- a/updates/restart.go +++ b/updates/restart.go @@ -21,21 +21,38 @@ var ( ) func init() { - restartTask = module.NewTask("automatic restart", automaticRestart) + restartTask = module.NewTask("automatic restart", automaticRestart).MaxDelay(10 * time.Minute) } -func triggerRestart(delay time.Duration) { +// DelayedRestart triggers a restart of the application by shutting down the +// module system gracefully and returning with RestartExitCode. The restart +// may be further delayed by up to 10 minutes by the internal task scheduling +// system. This only works if the process is managed by portmaster-start. +func DelayedRestart(delay time.Duration) { + log.Warningf("updates: restart triggered, will execute in %s", delay) + + // This enables TriggerRestartIfPending. + // Subsequent calls to TriggerRestart should be able to set a new delay. restartPending.Set() + + // Schedule the restart task. restartTask.Schedule(time.Now().Add(delay)) } -// TriggerRestartIfPending triggers an automatic restart, if one is pending. This can be used to prepone a scheduled restart if the conditions are preferable. +// TriggerRestartIfPending triggers an automatic restart, if one is pending. +// This can be used to prepone a scheduled restart if the conditions are preferable. func TriggerRestartIfPending() { if restartPending.IsSet() { _ = automaticRestart(module.Ctx, nil) } } +// RestartNow immediately executes a restart. +// This only works if the process is managed by portmaster-start. +func RestartNow() { + _ = automaticRestart(module.Ctx, nil) +} + func automaticRestart(_ context.Context, _ *modules.Task) error { if restartTriggered.SetToIf(false, true) { log.Info("updates: initiating automatic restart") diff --git a/updates/upgrader.go b/updates/upgrader.go index 3c353b7f..e03a4155 100644 --- a/updates/upgrader.go +++ b/updates/upgrader.go @@ -61,11 +61,8 @@ func upgrader(_ context.Context, _ interface{}) error { log.Warningf("updates: failed to upgrade portmaster-start: %s", err) } - binName := strings.TrimSuffix( - filepath.Base(os.Args[0]), - ".exe", - ) - switch binName { + binBaseName := strings.Split(filepath.Base(os.Args[0]), "_")[0] + switch binBaseName { case "portmaster-core": err = upgradeCoreNotify() if err != nil { @@ -83,23 +80,24 @@ func upgrader(_ context.Context, _ interface{}) error { } func upgradeCoreNotify() error { - // check if we can upgrade - if pmCoreUpdate == nil || pmCoreUpdate.UpgradeAvailable() { - identifier := "core/portmaster-core" // identifier, use forward slash! - if onWindows { - identifier += exeExt - } - - // get newest portmaster-core - new, err := GetPlatformFile(identifier) - if err != nil { - return err - } - pmCoreUpdate = new - } else { + if pmCoreUpdate != nil && !pmCoreUpdate.UpgradeAvailable() { return nil } + // make identifier + identifier := "core/portmaster-core" // identifier, use forward slash! + if onWindows { + identifier += exeExt + } + + // get newest portmaster-core + new, err := GetPlatformFile(identifier) + if err != nil { + return err + } + pmCoreUpdate = new + + // check for new version if info.GetInfo().Version != pmCoreUpdate.Version() { n := notifications.NotifyInfo( "updates:core-update-available", @@ -143,24 +141,24 @@ func upgradeHub() error { if hubUpgradeStarted { return nil } - - // check if we can upgrade - if spnHubUpdate == nil || spnHubUpdate.UpgradeAvailable() { - identifier := "hub/spn-hub" // identifier, use forward slash! - if onWindows { - identifier += exeExt - } - - // get newest spn-hub - new, err := GetPlatformFile(identifier) - if err != nil { - return err - } - spnHubUpdate = new - } else { + if spnHubUpdate != nil && !spnHubUpdate.UpgradeAvailable() { return nil } + // make identifier + identifier := "hub/spn-hub" // identifier, use forward slash! + if onWindows { + identifier += exeExt + } + + // get newest spn-hub + new, err := GetPlatformFile(identifier) + if err != nil { + return err + } + spnHubUpdate = new + + // check for new version if info.GetInfo().Version != spnHubUpdate.Version() { // get random delay with up to three hours delayMinutes, err := rng.Number(3 * 60) @@ -168,7 +166,7 @@ func upgradeHub() error { return err } - triggerRestart(time.Duration(delayMinutes) * time.Minute) + DelayedRestart(time.Duration(delayMinutes) * time.Minute) hubUpgradeStarted = true }