Improve start and shutdown controls and flow
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -9,44 +8,43 @@ import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/safing/portmaster/base/log"
|
||||
"github.com/safing/portmaster/service"
|
||||
"github.com/safing/portmaster/service/mgr"
|
||||
"github.com/safing/portmaster/spn/conf"
|
||||
)
|
||||
|
||||
var (
|
||||
printStackOnExit bool
|
||||
enableInputSignals bool
|
||||
|
||||
sigUSR1 = syscall.Signal(0xa) // dummy for windows
|
||||
)
|
||||
var printStackOnExit bool
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&printStackOnExit, "print-stack-on-exit", false, "prints the stack before of shutting down")
|
||||
flag.BoolVar(&enableInputSignals, "input-signals", false, "emulate signals using stdin")
|
||||
}
|
||||
|
||||
type SystemService interface {
|
||||
Run()
|
||||
IsService() bool
|
||||
RestartService() error
|
||||
}
|
||||
|
||||
func cmdRun(cmd *cobra.Command, args []string) {
|
||||
// Call platform specific checks, that will execute commands like "recover-iptables"
|
||||
platformSpecificChecks()
|
||||
// Run platform specific setup or switches.
|
||||
runPlatformSpecifics(cmd, args)
|
||||
|
||||
// SETUP
|
||||
|
||||
svcCfg.VerifyBinaryUpdates = nil // FIXME
|
||||
svcCfg.VerifyIntelUpdates = nil // FIXME
|
||||
|
||||
instance := createInstance()
|
||||
run(instance)
|
||||
}
|
||||
|
||||
func createInstance() *service.Instance {
|
||||
// enable SPN client mode
|
||||
conf.EnableClient(true)
|
||||
conf.EnableIntegration(true)
|
||||
|
||||
// Create instance.
|
||||
// Instance modules might request a cmdline execution of a function.
|
||||
var execCmdLine bool
|
||||
instance, err := service.New(svcCfg)
|
||||
switch {
|
||||
@@ -76,7 +74,56 @@ func createInstance() *service.Instance {
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
return instance
|
||||
|
||||
// START
|
||||
|
||||
// Set default log level and start logging.
|
||||
log.SetLogLevel(log.WarningLevel)
|
||||
_ = log.Start()
|
||||
|
||||
// Create system service.
|
||||
service := NewSystemService(instance)
|
||||
|
||||
// Start instance via system service manager.
|
||||
go func() {
|
||||
service.Run()
|
||||
}()
|
||||
|
||||
// SHUTDOWN
|
||||
|
||||
// Wait for shutdown to be started.
|
||||
<-instance.ShuttingDown()
|
||||
|
||||
// Wait for shutdown to be finished.
|
||||
select {
|
||||
case <-instance.ShutdownComplete():
|
||||
case <-time.After(3 * time.Minute):
|
||||
printStackTo(os.Stderr, "PRINTING STACK - TAKING TOO LONG FOR SHUTDOWN")
|
||||
}
|
||||
|
||||
// Stop logging.
|
||||
log.Shutdown()
|
||||
|
||||
// Print stack on shutdown, if enabled.
|
||||
if printStackOnExit {
|
||||
printStackTo(os.Stdout, "PRINTING STACK ON EXIT")
|
||||
}
|
||||
|
||||
// Check if restart was triggered and send start service command if true.
|
||||
if instance.ShouldRestart && service.IsService() {
|
||||
if err := service.RestartService(); err != nil {
|
||||
slog.Error("failed to restart service", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Give a small amount of time for everything to settle:
|
||||
// - All logs written.
|
||||
// - Restart command started, if needed.
|
||||
// - Windows service manager notified.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Exit
|
||||
os.Exit(instance.ExitCode())
|
||||
}
|
||||
|
||||
func printStackTo(writer io.Writer, msg string) {
|
||||
@@ -88,21 +135,3 @@ func printStackTo(writer io.Writer, msg string) {
|
||||
slog.Error("failed to write stack trace", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
func inputSignals(signalCh chan os.Signal) {
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
switch scanner.Text() {
|
||||
case "SIGHUP":
|
||||
signalCh <- syscall.SIGHUP
|
||||
case "SIGINT":
|
||||
signalCh <- syscall.SIGINT
|
||||
case "SIGQUIT":
|
||||
signalCh <- syscall.SIGQUIT
|
||||
case "SIGTERM":
|
||||
signalCh <- syscall.SIGTERM
|
||||
case "SIGUSR1":
|
||||
signalCh <- sigUSR1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user