diff --git a/account.go b/account.go index cdcccfe..f0954e8 100644 --- a/account.go +++ b/account.go @@ -44,11 +44,13 @@ func SetAccount(mxid string, name string, protocol string, config map[string]str return fmt.Errorf("Wrong protocol") } if !reflect.DeepEqual(config, prev_acct.Config) { - prev_acct.Conn.Close() - prev_acct.JoinedRooms = map[RoomID]bool{} + go func() { + prev_acct.Conn.Close() + prev_acct.JoinedRooms = map[RoomID]bool{} - prev_acct.Config = config - go prev_acct.connect() + prev_acct.Config = config + prev_acct.connect() + }() } } else { proto, ok := Protocols[protocol] @@ -128,11 +130,13 @@ func RemoveAccount(mxUser string, name string) { } } -func CloseAllAcountsForShutdown() { +func CloseAllAccountsForShutdown() { accountsLock.Lock() defer accountsLock.Unlock() + for _, accl := range registeredAccounts { for _, acct := range accl { + log.Printf("Closing %#v", acct) acct.Conn.Close() } } diff --git a/connector/external/external.go b/connector/external/external.go index b66ab6c..9896750 100644 --- a/connector/external/external.go +++ b/connector/external/external.go @@ -177,6 +177,7 @@ func (ext *External) restartLoop(generation int) { break } log.Printf("Process %s stopped, restarting.", ext.command) + log.Printf("Generation %d vs %d", ext.generation, generation) err := ext.setupProc(generation) if err != nil { ext.proc = nil @@ -326,22 +327,23 @@ func (ext *External) Close() { ext.sendJson.Encode(&extMessage{ MsgType: CLOSE, }) + ext.proc.Process.Signal(os.Interrupt) - proc := ext.proc - proc.Process.Signal(os.Interrupt) ext.recvPipe.Close() ext.sendPipe.Close() + go func() { + time.Sleep(1 * time.Second) + log.Info("Sending SIGKILL to external process (did not terminate within 1 second)") + ext.proc.Process.Kill() + }() + ext.proc.Wait() + ext.proc = nil ext.recvPipe = nil ext.sendPipe = nil ext.sendJson = nil ext.handlerChan = nil - - go func() { - time.Sleep(1 * time.Second) - proc.Process.Kill() - }() } // ---- Actual message handling :) diff --git a/connector/mattermost/mattermost.go b/connector/mattermost/mattermost.go index 0a632a9..ea49fd2 100644 --- a/connector/mattermost/mattermost.go +++ b/connector/mattermost/mattermost.go @@ -59,7 +59,7 @@ func (mm *Mattermost) Configure(c Configuration) error { } // Reinitialize shared data structures - mm.handlerStopChan = make(chan bool) + mm.handlerStopChan = make(chan bool, 1) mm.caches.mmusers = make(map[string]string) mm.caches.sentjoined = make(map[string]bool) diff --git a/external/messenger.py b/external/messenger.py index f8f1a43..01453ec 100755 --- a/external/messenger.py +++ b/external/messenger.py @@ -225,7 +225,7 @@ class MessengerBridge: self.client = MessengerBridgeClient(email=email, password=password, max_tries=1) if not self.client.isLoggedIn(): - return {"_type": "ret_error", "error": "Unable to login (?)"} + return {"_type": "rep_error", "error": "Unable to login (?)"} try: f = open(client_file, "wb") diff --git a/main.go b/main.go index a5b4394..1d62d9f 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,6 @@ import ( "os" "os/signal" "syscall" - "time" log "github.com/sirupsen/logrus" "gopkg.in/yaml.v2" @@ -176,44 +175,36 @@ func main() { reg_file := readRegistration(config.Registration) registration = ®_file - // Start appservice and web management interface + // Create context and handlers for errors and signals + ctx, stop_all := context.WithCancel(context.Background()) errch := make(chan error) sigch := make(chan os.Signal) signal.Notify(sigch, os.Interrupt, syscall.SIGTERM) + defer func() { + signal.Stop(sigch) + stop_all() + }() - as_server, err := StartAppService(errch) + // Start appservice and web server + _, err = StartAppService(errch, ctx) if err != nil { log.Fatal(err) } - web_server := StartWeb(errch) + _ = StartWeb(errch, ctx) // Wait for an error somewhere or interrupt signal select { case err = <-errch: - if err != nil { - log.Error(err) - } + log.Error(err) + stop_all() case sig := <-sigch: - log.Warnf("Got signal %s", sig.String()) + log.Warnf("Got signal: %s", sig.String()) + stop_all() + case <-ctx.Done(): } - // Shut down, hopefully this is not a too bad way to do it - log.Warn("Shuttind down") - delay := 2 * time.Second - - ctx1, _ := context.WithTimeout(context.TODO(), delay) - go as_server.Shutdown(ctx1) - - ctx2, _ := context.WithTimeout(context.TODO(), delay) - go web_server.Shutdown(ctx2) - - time.Sleep(delay) - CloseAllAcountsForShutdown() - - if err != nil { - os.Exit(1) - } else { - os.Exit(0) - } + log.Info("Closing all account connections...") + CloseAllAccountsForShutdown() + log.Info("Exiting.") } diff --git a/server.go b/server.go index ce0334a..294ad7f 100644 --- a/server.go +++ b/server.go @@ -1,8 +1,10 @@ package main import ( + "context" "encoding/json" "fmt" + "net" "net/http" "os" "strings" @@ -16,7 +18,7 @@ import ( var mx *mxlib.Client -func StartAppService(errch chan error) (*http.Server, error) { +func StartAppService(errch chan error, ctx context.Context) (*http.Server, error) { mx = mxlib.NewClient(config.Server, registration.AsToken) err := InitDb() @@ -56,6 +58,9 @@ func StartAppService(errch chan error) (*http.Server, error) { http_server := &http.Server{ Addr: config.ASBindAddr, Handler: checkTokenAndLog(router), + BaseContext: func(net.Listener) context.Context { + return ctx + }, } go func() { err := http_server.ListenAndServe() diff --git a/web.go b/web.go index 2a04a6c..c47a470 100644 --- a/web.go +++ b/web.go @@ -1,7 +1,9 @@ package main import ( + "context" "html/template" + "net" "net/http" "strconv" "strings" @@ -21,7 +23,7 @@ const SESSION_NAME = "easybridge_session" var sessionsStore sessions.Store = nil var userKeys = map[string]*[32]byte{} -func StartWeb(errch chan error) *http.Server { +func StartWeb(errch chan error, ctx context.Context) *http.Server { session_key := blake2b.Sum256([]byte(config.SessionKey)) sessionsStore = sessions.NewCookieStore(session_key[:]) @@ -39,6 +41,9 @@ func StartWeb(errch chan error) *http.Server { web_server := &http.Server{ Addr: config.WebBindAddr, Handler: logRequest(r), + BaseContext: func(net.Listener) context.Context { + return ctx + }, } go func() { err := web_server.ListenAndServe()