aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2020-03-04 17:44:22 +0100
committerAlex Auvolat <alex@adnab.me>2020-03-04 17:44:22 +0100
commitd4d3cc422b809d17daa18966ac95a852fc3045a5 (patch)
treee54ee18524568902b3d183a61d83d603ca78f6ab
parentdf1f2d38b3e5d31827bf1d07fa63d5eaed6bc682 (diff)
downloadeasybridge-d4d3cc422b809d17daa18966ac95a852fc3045a5.tar.gz
easybridge-d4d3cc422b809d17daa18966ac95a852fc3045a5.zip
Improve exiting (actually it was Mattermost that was creating a deadlock)
-rw-r--r--account.go14
-rw-r--r--connector/external/external.go16
-rw-r--r--connector/mattermost/mattermost.go2
-rwxr-xr-xexternal/messenger.py2
-rw-r--r--main.go43
-rw-r--r--server.go7
-rw-r--r--web.go7
7 files changed, 49 insertions, 42 deletions
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 = &reg_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()