mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
[WIP] Add restart command to instance
This commit is contained in:
parent
c9631daa3e
commit
61babe2822
15 changed files with 81 additions and 98 deletions
|
@ -55,7 +55,10 @@ func initialize() *service.Instance {
|
|||
|
||||
// Create instance.
|
||||
var execCmdLine bool
|
||||
instance, err := service.New(&service.ServiceConfig{})
|
||||
instance, err := service.New(&service.ServiceConfig{
|
||||
IsRunningAsService: isRunningAsService(),
|
||||
DefaultRestartCommand: defaultRestartCommand,
|
||||
})
|
||||
switch {
|
||||
case err == nil:
|
||||
// Continue
|
||||
|
|
|
@ -4,14 +4,19 @@ import (
|
|||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
processInfo "github.com/shirou/gopsutil/process"
|
||||
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/service"
|
||||
)
|
||||
|
||||
var defaultRestartCommand = exec.Command("systemctl", "restart", "portmaster")
|
||||
|
||||
func run(instance *service.Instance) {
|
||||
// Set default log level.
|
||||
log.SetLogLevel(log.WarningLevel)
|
||||
|
@ -98,3 +103,20 @@ func run(instance *service.Instance) {
|
|||
|
||||
os.Exit(instance.ExitCode())
|
||||
}
|
||||
|
||||
func isRunningAsService() bool {
|
||||
// Get the current process ID
|
||||
pid := os.Getpid()
|
||||
|
||||
currentProcess, err := processInfo.NewProcess(int32(pid))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
ppid, err := currentProcess.Ppid()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// Check if the parent process ID is 1 == init system
|
||||
return ppid == 1
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
@ -24,6 +25,8 @@ var (
|
|||
// wait groups
|
||||
runWg sync.WaitGroup
|
||||
finishWg sync.WaitGroup
|
||||
|
||||
defaultRestartCommand = exec.Command("sc.exe", "restart", "PortmasterCore")
|
||||
)
|
||||
|
||||
const serviceName = "PortmasterCore"
|
||||
|
@ -168,3 +171,11 @@ func registerSignalHandler(instance *service.Instance) {
|
|||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func isRunningAsService() bool {
|
||||
isService, err := svc.IsWindowsService()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return isService
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
package service
|
||||
|
||||
type ServiceConfig struct{}
|
||||
import "os/exec"
|
||||
|
||||
type ServiceConfig struct {
|
||||
IsRunningAsService bool
|
||||
DefaultRestartCommand *exec.Cmd
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/safing/portmaster/service/process"
|
||||
"github.com/safing/portmaster/service/resolver"
|
||||
"github.com/safing/portmaster/service/status"
|
||||
"github.com/safing/portmaster/service/updates"
|
||||
"github.com/safing/portmaster/spn/captain"
|
||||
)
|
||||
|
||||
|
@ -149,8 +148,8 @@ func shutdown(_ *api.Request) (msg string, err error) {
|
|||
func restart(_ *api.Request) (msg string, err error) {
|
||||
log.Info("core: user requested restart via action")
|
||||
|
||||
// Let the updates module handle restarting.
|
||||
updates.RestartNow()
|
||||
// Trigger restart
|
||||
module.instance.Restart()
|
||||
|
||||
return "restart initiated", nil
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ func New(instance instance) (*Core, error) {
|
|||
|
||||
type instance interface {
|
||||
Shutdown()
|
||||
Restart()
|
||||
AddWorkerInfoToDebugInfo(di *debug.Info)
|
||||
BinaryUpdates() *updates.Updates
|
||||
IntelUpdates() *updates.Updates
|
||||
|
|
|
@ -4,14 +4,17 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
go_runtime "runtime"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/base/api"
|
||||
"github.com/safing/portmaster/base/config"
|
||||
"github.com/safing/portmaster/base/database/dbmodule"
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/base/metrics"
|
||||
"github.com/safing/portmaster/base/notifications"
|
||||
"github.com/safing/portmaster/base/rng"
|
||||
|
@ -102,6 +105,8 @@ type Instance struct {
|
|||
terminal *terminal.TerminalModule
|
||||
|
||||
CommandLineOperation func() error
|
||||
isRunningAsService bool
|
||||
defaultRestartCommand *exec.Cmd
|
||||
}
|
||||
|
||||
func getCurrentBinaryFolder() (string, error) {
|
||||
|
@ -178,6 +183,8 @@ func New(svcCfg *ServiceConfig) (*Instance, error) { //nolint:maintidx
|
|||
// Create instance to pass it to modules.
|
||||
instance := &Instance{}
|
||||
instance.ctx, instance.cancelCtx = context.WithCancel(context.Background())
|
||||
instance.isRunningAsService = svcCfg.IsRunningAsService
|
||||
instance.defaultRestartCommand = svcCfg.DefaultRestartCommand
|
||||
|
||||
var err error
|
||||
|
||||
|
@ -671,7 +678,7 @@ func (i *Instance) Restart() {
|
|||
i.core.EventRestart.Submit(struct{}{})
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
i.shutdown(RestartExitCode)
|
||||
i.serviceRestart()
|
||||
}
|
||||
|
||||
// Shutdown asynchronously stops the instance.
|
||||
|
@ -700,6 +707,25 @@ func (i *Instance) shutdown(exitCode int) {
|
|||
})
|
||||
}
|
||||
|
||||
func (i *Instance) serviceRestart() {
|
||||
if !i.isRunningAsService {
|
||||
i.shutdown(RestartExitCode)
|
||||
return
|
||||
}
|
||||
cmd := i.defaultRestartCommand
|
||||
|
||||
// Check if user defined custom command for restarting the service.
|
||||
restartCommand, exists := os.LookupEnv("PORTMASTER_RESTART_COMMAND")
|
||||
|
||||
log.Debugf(`instance: running command "%s", %v`, restartCommand, exists)
|
||||
if exists && restartCommand != "" {
|
||||
commandSplit := strings.Split(restartCommand, " ")
|
||||
cmd = exec.Command(commandSplit[0], commandSplit[1:]...)
|
||||
}
|
||||
log.Debugf("instance: running command %s", cmd.String())
|
||||
_ = cmd.Run()
|
||||
}
|
||||
|
||||
// Stopping returns whether the instance is shutting down.
|
||||
func (i *Instance) Stopping() bool {
|
||||
return i.ctx.Err() != nil
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"strings"
|
||||
|
||||
semver "github.com/hashicorp/go-version"
|
||||
|
||||
"github.com/safing/portmaster/base/log"
|
||||
)
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package updates
|
|
@ -1 +0,0 @@
|
|||
package updates
|
|
@ -150,7 +150,7 @@ func (u *Updates) applyUpdates(_ *mgr.WorkerCtx) error {
|
|||
// Perform restart.
|
||||
u.instance.Restart()
|
||||
} else {
|
||||
// Update completed and no restart was needed. Submit an event.
|
||||
// Update completed and no restart is needed. Submit an event.
|
||||
u.EventResourcesUpdated.Submit(struct{}{})
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
semver "github.com/hashicorp/go-version"
|
||||
|
||||
"github.com/safing/portmaster/base/log"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
package updates
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tevino/abool"
|
||||
|
||||
"github.com/safing/portmaster/base/log"
|
||||
)
|
||||
|
||||
var (
|
||||
// RebootOnRestart defines whether the whole system, not just the service,
|
||||
// should be restarted automatically when triggering a restart internally.
|
||||
RebootOnRestart bool
|
||||
|
||||
restartPending = abool.New()
|
||||
restartTriggered = abool.New()
|
||||
|
||||
restartTime time.Time
|
||||
restartTimeLock sync.Mutex
|
||||
)
|
||||
|
||||
// IsRestarting returns whether a restart has been triggered.
|
||||
func IsRestarting() bool {
|
||||
return restartTriggered.IsSet()
|
||||
}
|
||||
|
||||
// RestartIsPending returns whether a restart is pending.
|
||||
func RestartIsPending() (pending bool, restartAt time.Time) {
|
||||
if restartPending.IsNotSet() {
|
||||
return false, time.Time{}
|
||||
}
|
||||
|
||||
restartTimeLock.Lock()
|
||||
defer restartTimeLock.Unlock()
|
||||
|
||||
return true, restartTime
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// Check if restart is already pending.
|
||||
if !restartPending.SetToIf(false, true) {
|
||||
return
|
||||
}
|
||||
|
||||
// Schedule the restart task.
|
||||
log.Warningf("updates: restart triggered, will execute in %s", delay)
|
||||
restartAt := time.Now().Add(delay)
|
||||
// module.restartWorkerMgr.Delay(delay)
|
||||
|
||||
// Set restartTime.
|
||||
restartTimeLock.Lock()
|
||||
defer restartTimeLock.Unlock()
|
||||
restartTime = restartAt
|
||||
}
|
||||
|
||||
// AbortRestart aborts a (delayed) restart.
|
||||
func AbortRestart() {
|
||||
if restartPending.SetToIf(true, false) {
|
||||
log.Warningf("updates: restart aborted")
|
||||
|
||||
// Cancel schedule.
|
||||
// module.restartWorkerMgr.Delay(0)
|
||||
}
|
||||
}
|
||||
|
||||
// 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() {
|
||||
// module.restartWorkerMgr.Go()
|
||||
// }
|
||||
}
|
||||
|
||||
// RestartNow immediately executes a restart.
|
||||
// This only works if the process is managed by portmaster-start.
|
||||
func RestartNow() {
|
||||
restartPending.Set()
|
||||
// module.restartWorkerMgr.Go()
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package captain
|
||||
|
||||
import (
|
||||
"github.com/safing/portmaster/service/updates"
|
||||
"github.com/safing/portmaster/spn/conf"
|
||||
"github.com/safing/portmaster/spn/docks"
|
||||
)
|
||||
|
@ -41,5 +40,7 @@ func updateConnectionStatus() {
|
|||
return
|
||||
}
|
||||
}
|
||||
updates.TriggerRestartIfPending()
|
||||
|
||||
// TODO(vladimir): what was this needed for?
|
||||
// updates.TriggerRestartIfPending()
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func updateSPNIntel(_ context.Context, _ interface{}) (err error) {
|
|||
|
||||
// Check if there is something to do.
|
||||
// TODO(vladimir): is update check needed
|
||||
if intelResource != nil { //&& !intelResource.UpgradeAvailable() {
|
||||
if intelResource != nil { // && !intelResource.UpgradeAvailable() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue