get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/signal_windows.go (about) 1 // Copyright 2012-2019 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "fmt" 18 "os" 19 "os/signal" 20 "syscall" 21 "time" 22 23 "golang.org/x/sys/windows/svc" 24 "golang.org/x/sys/windows/svc/mgr" 25 ) 26 27 // Signal Handling 28 func (s *Server) handleSignals() { 29 if s.getOpts().NoSigs { 30 return 31 } 32 c := make(chan os.Signal, 1) 33 34 signal.Notify(c, os.Interrupt, syscall.SIGTERM) 35 36 go func() { 37 for { 38 select { 39 case sig := <-c: 40 s.Debugf("Trapped %q signal", sig) 41 s.Shutdown() 42 os.Exit(0) 43 case <-s.quitCh: 44 return 45 } 46 } 47 }() 48 } 49 50 // ProcessSignal sends the given signal command to the running nats-server service. 51 // If service is empty, this signals the "nats-server" service. This returns an 52 // error is the given service is not running or the command is invalid. 53 func ProcessSignal(command Command, service string) error { 54 if service == "" { 55 service = serviceName 56 } 57 58 m, err := mgr.Connect() 59 if err != nil { 60 return err 61 } 62 defer m.Disconnect() 63 64 s, err := m.OpenService(service) 65 if err != nil { 66 return fmt.Errorf("could not access service: %v", err) 67 } 68 defer s.Close() 69 70 var ( 71 cmd svc.Cmd 72 to svc.State 73 ) 74 75 switch command { 76 case CommandStop, CommandQuit: 77 cmd = svc.Stop 78 to = svc.Stopped 79 case CommandReopen: 80 cmd = reopenLogCmd 81 to = svc.Running 82 case CommandReload: 83 cmd = svc.ParamChange 84 to = svc.Running 85 case commandLDMode: 86 cmd = ldmCmd 87 to = svc.Running 88 default: 89 return fmt.Errorf("unknown signal %q", command) 90 } 91 92 status, err := s.Control(cmd) 93 if err != nil { 94 return fmt.Errorf("could not send control=%d: %v", cmd, err) 95 } 96 97 timeout := time.Now().Add(10 * time.Second) 98 for status.State != to { 99 if timeout.Before(time.Now()) { 100 return fmt.Errorf("timeout waiting for service to go to state=%d", to) 101 } 102 time.Sleep(300 * time.Millisecond) 103 status, err = s.Query() 104 if err != nil { 105 return fmt.Errorf("could not retrieve service status: %v", err) 106 } 107 } 108 109 return nil 110 }