diff --git a/cmd/dbmigrate/main.go b/cmd/dbmigrate/main.go index bff65642..f88234e7 100644 --- a/cmd/dbmigrate/main.go +++ b/cmd/dbmigrate/main.go @@ -108,15 +108,14 @@ func main() { err = temp.LoadMigrations() if err != nil { fmt.Println(err) - os.Exit(0) + os.Exit(1) } conf := config.GetConfig() - err = conf.LoadConfig(configFile) if err != nil { fmt.Println(err) - os.Exit(0) + os.Exit(1) } err = openDbConnection(conf.Database.Driver) @@ -130,7 +129,6 @@ func main() { temp.Conn = dbConn err = temp.RunMigration() - if err != nil { fmt.Println(err) os.Exit(1) diff --git a/engine/engine.go b/engine/engine.go index a3d577f3..88d0e611 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -4,10 +4,7 @@ import ( "errors" "flag" "fmt" - "os" - "os/signal" "sync" - "syscall" "time" "github.com/thrasher-corp/gocryptotrader/common" @@ -35,7 +32,6 @@ type Engine struct { PortfolioManager portfolioManager CommsManager commsManager DepositAddressManager *DepositAddressManager - Shutdown chan struct{} Settings Settings Uptime time.Time ServicesWG sync.WaitGroup @@ -98,7 +94,6 @@ func NewFromSettings(settings *Settings) (*Engine, error) { return nil, fmt.Errorf("unable to adjust runtime GOMAXPROCS value. Err: %s", err) } - b.handleInterrupt() ValidateSettings(&b, settings) return &b, nil } @@ -256,11 +251,9 @@ func PrintSettings(s *Settings) { } // Start starts the engine -func (e *Engine) Start() { - // TO-DO: move this out of here +func (e *Engine) Start() error { if e == nil { - log.Errorln(log.Global, "Engine instance is nil") - os.Exit(1) + return errors.New("engine instance is nil") } if e.Settings.EnableDatabaseManager { @@ -302,10 +295,8 @@ func (e *Engine) Start() { log.Debugln(log.Global, "Setting up exchanges..") SetupExchanges() - // TO-DO: move this out of here if len(Bot.Exchanges) == 0 { - log.Errorln(log.Global, "No exchanges were able to be loaded. Exiting") - os.Exit(1) + return errors.New("no exchanges are loaded") } if e.Settings.EnableCommsRelayer { @@ -394,8 +385,7 @@ func (e *Engine) Start() { go WebsocketRoutine() } - <-e.Shutdown - e.Stop() + return nil } // Stop correctly shuts down engine saving configuration files @@ -453,24 +443,8 @@ func (e *Engine) Stop() { // Wait for services to gracefully shutdown e.ServicesWG.Wait() - log.Debugln(log.Global, "Exiting.") err := log.CloseLogger() if err != nil { fmt.Printf("Failed to close logger %v", err) } - - os.Exit(0) -} - -// handleInterrupt monitors and captures the SIGTERM in a new goroutine then -// shuts down the engine instance -func (e *Engine) handleInterrupt() { - c := make(chan os.Signal, 1) - e.Shutdown = make(chan struct{}) - signal.Notify(c, os.Interrupt, syscall.SIGTERM) - go func() { - sig := <-c - log.Debugf(log.Global, "Captured %v, shutdown requested.\n", sig) - close(e.Shutdown) - }() } diff --git a/main.go b/main.go index b4c3b55e..4638fa38 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/engine" "github.com/thrasher-corp/gocryptotrader/exchanges/request" log "github.com/thrasher-corp/gocryptotrader/logger" + "github.com/thrasher-corp/gocryptotrader/signaler" ) func main() { @@ -93,10 +94,18 @@ func main() { engine.Bot, err = engine.NewFromSettings(&settings) if engine.Bot == nil || err != nil { - log.Errorf(log.Global, "Unable to initialise bot engine. Err: %s\n", err) + log.Errorf(log.Global, "Unable to initialise bot engine. Error: %s\n", err) os.Exit(1) } engine.PrintSettings(&engine.Bot.Settings) - engine.Bot.Start() + if err = engine.Bot.Start(); err != nil { + log.Errorf(log.Global, "Unable to start bot engine. Error: %s\n", err) + os.Exit(1) + } + + interrupt := signaler.WaitForInterrupt() + log.Infof(log.Global, "Captured %v, shutdown requested.\n", interrupt) + engine.Bot.Stop() + log.Infoln(log.Global, "Exiting.") } diff --git a/signaler/signaler.go b/signaler/signaler.go new file mode 100644 index 00000000..d2b70a07 --- /dev/null +++ b/signaler/signaler.go @@ -0,0 +1,28 @@ +package signaler + +import ( + "os" + "os/signal" + "syscall" +) + +var ( + s = make(chan os.Signal, 1) +) + +func init() { + sigs := []os.Signal{ + os.Interrupt, + os.Kill, + syscall.SIGTERM, + syscall.SIGQUIT, + syscall.SIGABRT, + } + signal.Notify(s, sigs...) +} + +// WaitForInterrupt waits until a os.Signal is +// received and returns the result +func WaitForInterrupt() os.Signal { + return <-s +}