From 6e8299278000ed187c6795d31a389890dc3435cc Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 19 Nov 2019 00:23:00 +0100 Subject: [PATCH 1/2] (cosmetic) reorganized runDaemonCommand in a more straighforward way --- cli/daemon/daemon.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index bfbdeea0f92..ee95a9e9154 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -50,27 +50,28 @@ func NewCommand() *cobra.Command { } func runDaemonCommand(cmd *cobra.Command, args []string) { - lis, err := net.Listen("tcp", port) - if err != nil { - log.Fatalf("failed to listen: %v", err) - } s := grpc.NewServer() - userAgentValue := fmt.Sprintf("%s/%s daemon (%s; %s; %s) Commit:%s", globals.VersionInfo.Application, - globals.VersionInfo.VersionString, runtime.GOARCH, runtime.GOOS, runtime.Version(), globals.VersionInfo.Commit) - headers := http.Header{"User-Agent": []string{userAgentValue}} - // register the commands service - coreServer := daemon.ArduinoCoreServerImpl{ + headers := http.Header{"User-Agent": []string{ + fmt.Sprintf("%s/%s daemon (%s; %s; %s) Commit:%s", + globals.VersionInfo.Application, + globals.VersionInfo.VersionString, + runtime.GOARCH, runtime.GOOS, + runtime.Version(), globals.VersionInfo.Commit)}} + srv_commands.RegisterArduinoCoreServer(s, &daemon.ArduinoCoreServerImpl{ DownloaderHeaders: headers, VersionString: globals.VersionInfo.VersionString, Config: globals.Config, - } - srv_commands.RegisterArduinoCoreServer(s, &coreServer) + }) // register the monitors service srv_monitor.RegisterMonitorServer(s, &daemon.MonitorService{}) + lis, err := net.Listen("tcp", port) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } From bc9f1ad7e0d43e91651b65169e76315c2ebf5819 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 19 Nov 2019 15:06:29 +0100 Subject: [PATCH 2/2] daemon: terminate on parent process ending; added --daemonize flag This is useful when the cli daemon is launched from an external process to avoid leaving zombie process if the parent process unexpectedly dies. If daemonization (so no stdin/stdout) is the intended behaviour the --daemonize flag must be used. --- cli/daemon/daemon.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index ee95a9e9154..643f20a47a4 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -19,6 +19,8 @@ package daemon import ( "fmt" + "io" + "io/ioutil" "log" "net" "net/http" @@ -39,7 +41,7 @@ const ( // NewCommand created a new `daemon` command func NewCommand() *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "daemon", Short: fmt.Sprintf("Run as a daemon on port %s", port), Long: "Running as a daemon the initialization of cores and libraries is done only once.", @@ -47,8 +49,12 @@ func NewCommand() *cobra.Command { Args: cobra.NoArgs, Run: runDaemonCommand, } + cmd.Flags().BoolVar(&daemonize, "daemonize", false, "Do not terminate daemon process if the parent process dies") + return cmd } +var daemonize bool + func runDaemonCommand(cmd *cobra.Command, args []string) { s := grpc.NewServer() @@ -68,6 +74,15 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { // register the monitors service srv_monitor.RegisterMonitorServer(s, &daemon.MonitorService{}) + if !daemonize { + // When parent process ends terminate also the daemon + go func() { + // stdin is closed when the controlling parent process ends + _, _ = io.Copy(ioutil.Discard, os.Stdin) + os.Exit(0) + }() + } + lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("failed to listen: %v", err) @@ -75,6 +90,4 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } - - fmt.Println("Done serving") }