Improve exiting (actually it was Mattermost that was creating a deadlock)

This commit is contained in:
Alex 2020-03-04 17:44:22 +01:00
parent df1f2d38b3
commit d4d3cc422b
7 changed files with 49 additions and 42 deletions

View file

@ -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) {
go func() {
prev_acct.Conn.Close()
prev_acct.JoinedRooms = map[RoomID]bool{}
prev_acct.Config = config
go prev_acct.connect()
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()
}
}

View file

@ -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 :)

View file

@ -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)

View file

@ -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")

41
main.go
View file

@ -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)
}
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.")
}

View file

@ -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()

7
web.go
View file

@ -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()