fix(GODT-2500): Recover in deferred function.

This commit is contained in:
Jakub
2023-04-04 15:27:03 +02:00
parent fd100eecc2
commit 7330406752
18 changed files with 103 additions and 85 deletions

View File

@ -325,7 +325,11 @@ run-nogui: build-nogui clean-vendor gofiles
PROTONMAIL_ENV=dev ./${LAUNCHER_EXE} ${RUN_FLAGS} -c PROTONMAIL_ENV=dev ./${LAUNCHER_EXE} ${RUN_FLAGS} -c
run-debug: run-debug:
dlv debug ./cmd/Desktop-Bridge/main.go -- -l=debug dlv debug \
--build-flags "-ldflags '-X github.com/ProtonMail/proton-bridge/v3/internal/constants.Version=3.1.0+git'" \
./cmd/Desktop-Bridge/main.go \
-- \
-n -l=trace
ifeq "${TARGET_OS}" "windows" ifeq "${TARGET_OS}" "windows"
EXE_SUFFIX=.exe EXE_SUFFIX=.exe

View File

@ -25,6 +25,7 @@ import (
"time" "time"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/crash" "github.com/ProtonMail/proton-bridge/v3/internal/crash"
@ -62,7 +63,7 @@ func main() { //nolint:funlen
reporter := sentry.NewReporter(appName, useragent.New()) reporter := sentry.NewReporter(appName, useragent.New())
crashHandler := crash.NewHandler(reporter.ReportException) crashHandler := crash.NewHandler(reporter.ReportException)
defer crashHandler.HandlePanic() defer async.HandlePanic(crashHandler)
locationsProvider, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName)) locationsProvider, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName))
if err != nil { if err != nil {

4
go.mod
View File

@ -5,9 +5,9 @@ go 1.18
require ( require (
github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557
github.com/Masterminds/semver/v3 v3.2.0 github.com/Masterminds/semver/v3 v3.2.0
github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8 github.com/ProtonMail/gluon v0.15.1-0.20230405065656-e75e877aede1
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a
github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa github.com/ProtonMail/go-proton-api v0.4.1-0.20230405072218-d91d6600a52e
github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/ProtonMail/gopenpgp/v2 v2.5.2
github.com/PuerkitoBio/goquery v1.8.1 github.com/PuerkitoBio/goquery v1.8.1
github.com/abiosoft/ishell v2.0.0+incompatible github.com/abiosoft/ishell v2.0.0+incompatible

8
go.sum
View File

@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs
github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo=
github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk=
github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g=
github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8 h1:USMR8imbxkP4Ailch4ceV3hCZTaANMIGHhb5rpZFYn4= github.com/ProtonMail/gluon v0.15.1-0.20230405065656-e75e877aede1 h1:DLz6hm2Sb04dwWzzrXm14wRVzNYSuA0aOjWfnAF3cmw=
github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/gluon v0.15.1-0.20230405065656-e75e877aede1/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI=
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4=
github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4=
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
@ -40,8 +40,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297
github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4=
github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA=
github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM=
github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa h1:0JKWkz/gIYf+eky0dCFeBWrjEDLf59lS8HOlXtvn6Nk= github.com/ProtonMail/go-proton-api v0.4.1-0.20230405072218-d91d6600a52e h1:ZCvETTjO4oefRtBFG7jHdYZKKybkEcSkisSsKvSG5og=
github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa/go.mod h1:RfpLBcTIhfjOIcBhh7f36LtAOEi0mqPd3t8gyLWmCZM= github.com/ProtonMail/go-proton-api v0.4.1-0.20230405072218-d91d6600a52e/go.mod h1:tsV8BDWZcrV3oYI7ZhpCozg8NC09Nw48IGZkprgcM7o=
github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg=
github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs=
github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw=

View File

@ -28,6 +28,7 @@ import (
"time" "time"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/cookies" "github.com/ProtonMail/proton-bridge/v3/internal/cookies"
@ -379,7 +380,7 @@ func withCrashHandler(restarter *restarter.Restarter, reporter *sentry.Reporter,
defer logrus.Debug("Crash handler stopped") defer logrus.Debug("Crash handler stopped")
crashHandler := crash.NewHandler(crash.ShowErrorNotification(constants.FullAppName)) crashHandler := crash.NewHandler(crash.ShowErrorNotification(constants.FullAppName))
defer crashHandler.HandlePanic() defer async.HandlePanic(crashHandler)
// On crash, send crash report to Sentry. // On crash, send crash report to Sentry.
crashHandler.AddRecoveryAction(reporter.ReportException) crashHandler.AddRecoveryAction(reporter.ReportException)

View File

@ -46,10 +46,11 @@ func runFrontend(
switch { switch {
case c.Bool(flagCLI): case c.Bool(flagCLI):
return bridgeCLI.New(bridge, restarter, eventCh, crashHandler).Loop() return bridgeCLI.New(bridge, restarter, eventCh, crashHandler, quitCh).Loop()
case c.Bool(flagNonInteractive): case c.Bool(flagNonInteractive):
select {} <-quitCh
return nil
case c.Bool(flagGRPC): case c.Bool(flagGRPC):
service, err := grpc.NewService(crashHandler, restarter, locations, bridge, eventCh, quitCh, !c.Bool(flagNoWindow), parentPID) service, err := grpc.NewService(crashHandler, restarter, locations, bridge, eventCh, quitCh, !c.Bool(flagNoWindow), parentPID)

View File

@ -40,7 +40,7 @@ func checkSingleInstance(settingPath, lockFilePath string, curVersion *semver.Ve
return lock, nil return lock, nil
} }
logrus.Debug("Failed to create lock file; another instance is running") logrus.Warn("Failed to create lock file; another instance is running")
// We couldn't create the lock file, so another instance is probably running. // We couldn't create the lock file, so another instance is probably running.
// Check if it's an older version of the app. // Check if it's an older version of the app.

View File

@ -45,7 +45,7 @@ func NewMocks(tb testing.TB, version, minAuto *semver.Version) *Mocks {
mocks.TLSReporter.EXPECT().GetTLSIssueCh().Return(mocks.TLSIssueCh).AnyTimes() mocks.TLSReporter.EXPECT().GetTLSIssueCh().Return(mocks.TLSIssueCh).AnyTimes()
// This is called at he end of any go-routine: // This is called at he end of any go-routine:
mocks.CrashHandler.EXPECT().HandlePanic().AnyTimes() mocks.CrashHandler.EXPECT().HandlePanic(gomock.Any()).AnyTimes()
return mocks return mocks
} }

View File

@ -1,5 +1,5 @@
// Code generated by MockGen. DO NOT EDIT. // Code generated by MockGen. DO NOT EDIT.
// Source: github.com/ProtonMail/proton-bridge/v3/internal/async (interfaces: PanicHandler) // Source: github.com/ProtonMail/gluon/async (interfaces: PanicHandler)
// Package mocks is a generated GoMock package. // Package mocks is a generated GoMock package.
package mocks package mocks
@ -34,13 +34,13 @@ func (m *MockPanicHandler) EXPECT() *MockPanicHandlerMockRecorder {
} }
// HandlePanic mocks base method. // HandlePanic mocks base method.
func (m *MockPanicHandler) HandlePanic() { func (m *MockPanicHandler) HandlePanic(arg0 interface{}) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
m.ctrl.Call(m, "HandlePanic") m.ctrl.Call(m, "HandlePanic", arg0)
} }
// HandlePanic indicates an expected call of HandlePanic. // HandlePanic indicates an expected call of HandlePanic.
func (mr *MockPanicHandlerMockRecorder) HandlePanic() *gomock.Call { func (mr *MockPanicHandlerMockRecorder) HandlePanic(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandlePanic", reflect.TypeOf((*MockPanicHandler)(nil).HandlePanic), arg0)
} }

View File

@ -38,14 +38,16 @@ func (h *Handler) AddRecoveryAction(action RecoveryAction) *Handler {
return h return h
} }
func (h *Handler) HandlePanic() { func (h *Handler) HandlePanic(r interface{}) {
sentry.SkipDuringUnwind() sentry.SkipDuringUnwind()
if r := recover(); r != nil { if r == nil {
for _, action := range h.actions { return
if err := action(r); err != nil { }
logrus.WithError(err).Error("Failed to execute recovery action")
} for _, action := range h.actions {
if err := action(r); err != nil {
logrus.WithError(err).Error("Failed to execute recovery action")
} }
} }
} }

View File

@ -21,38 +21,41 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/ProtonMail/gluon/async"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestHandler(t *testing.T) { func TestHandler(t *testing.T) {
var s string assert.NotPanics(t, func() {
var s string
h := NewHandler( h := NewHandler(
func(r interface{}) error { func(r interface{}) error {
s += fmt.Sprintf("1: %v\n", r) s += fmt.Sprintf("1: %v\n", r)
return nil return nil
}, },
func(r interface{}) error { func(r interface{}) error {
s += fmt.Sprintf("2: %v\n", r) s += fmt.Sprintf("2: %v\n", r)
return nil return nil
}, },
) )
h. h.
AddRecoveryAction(func(r interface{}) error { AddRecoveryAction(func(r interface{}) error {
s += fmt.Sprintf("3: %v\n", r) s += fmt.Sprintf("3: %v\n", r)
return nil return nil
}). }).
AddRecoveryAction(func(r interface{}) error { AddRecoveryAction(func(r interface{}) error {
s += fmt.Sprintf("4: %v\n", r) s += fmt.Sprintf("4: %v\n", r)
return nil return nil
}) })
defer func() { defer func() {
assert.Equal(t, "1: thing\n2: thing\n3: thing\n4: thing\n", s) assert.Equal(t, "1: thing\n2: thing\n3: thing\n4: thing\n", s)
}() }()
defer h.HandlePanic() defer async.HandlePanic(h)
panic("thing") panic("thing")
})
} }

View File

@ -45,7 +45,13 @@ type frontendCLI struct {
} }
// New returns a new CLI frontend configured with the given options. // New returns a new CLI frontend configured with the given options.
func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan events.Event, panicHandler async.PanicHandler) *frontendCLI { //nolint:revive func New(
bridge *bridge.Bridge,
restarter *restarter.Restarter,
eventCh <-chan events.Event,
panicHandler async.PanicHandler,
quitCh <-chan struct{},
) *frontendCLI { //nolint:revive
fe := &frontendCLI{ fe := &frontendCLI{
Shell: ishell.New(), Shell: ishell.New(),
bridge: bridge, bridge: bridge,
@ -285,6 +291,11 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e
go fe.watchEvents(eventCh) go fe.watchEvents(eventCh)
go func() {
<-quitCh
fe.Close()
}()
return fe return fe
} }

View File

@ -70,7 +70,7 @@ type Service struct { // nolint:structcheck
eventQueue []*StreamEvent eventQueue []*StreamEvent
eventQueueMutex sync.Mutex eventQueueMutex sync.Mutex
panicHandler CrashHandler panicHandler async.PanicHandler
restarter Restarter restarter Restarter
bridge *bridge.Bridge bridge *bridge.Bridge
eventCh <-chan events.Event eventCh <-chan events.Event
@ -97,7 +97,7 @@ type Service struct { // nolint:structcheck
// NewService returns a new instance of the service. // NewService returns a new instance of the service.
func NewService( func NewService(
panicHandler CrashHandler, panicHandler async.PanicHandler,
restarter Restarter, restarter Restarter,
locations service.Locator, locations service.Locator,
bridge *bridge.Bridge, bridge *bridge.Bridge,
@ -192,10 +192,6 @@ func NewService(
return s, nil return s, nil
} }
func (s *Service) handlePanic() {
async.HandlePanic(s.panicHandler)
}
func (s *Service) initAutostart() { func (s *Service) initAutostart() {
s.firstTimeAutostart.Do(func() { s.firstTimeAutostart.Do(func() {
shouldAutostartBeOn := s.bridge.GetAutostart() shouldAutostartBeOn := s.bridge.GetAutostart()
@ -213,13 +209,13 @@ func (s *Service) Loop() error {
s.log.Info("Not monitoring parent PID") s.log.Info("Not monitoring parent PID")
} else { } else {
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
s.monitorParentPID() s.monitorParentPID()
}() }()
} }
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
s.watchEvents() s.watchEvents()
}() }()
@ -229,7 +225,7 @@ func (s *Service) Loop() error {
defer close(doneCh) defer close(doneCh)
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
select { select {
case <-s.quitCh: case <-s.quitCh:
@ -577,7 +573,7 @@ func (s *Service) monitorParentPID() {
s.log.Info("Parent process does not exist anymore. Initiating shutdown") s.log.Info("Parent process does not exist anymore. Initiating shutdown")
// quit will write to the parentPIDDoneCh, so we launch a goroutine. // quit will write to the parentPIDDoneCh, so we launch a goroutine.
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
if err := s.quit(); err != nil { if err := s.quit(); err != nil {
logrus.WithError(err).Error("Error on quit") logrus.WithError(err).Error("Error on quit")

View File

@ -26,6 +26,7 @@ import (
"runtime" "runtime"
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api"
"github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
@ -114,7 +115,7 @@ func (s *Service) Quit(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empt
func (s *Service) quit() error { func (s *Service) quit() error {
// Windows is notably slow at Quitting. We do it in a goroutine to speed things up a bit. // Windows is notably slow at Quitting. We do it in a goroutine to speed things up a bit.
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
if s.parentPID >= 0 { if s.parentPID >= 0 {
s.parentPIDDoneCh <- struct{}{} s.parentPIDDoneCh <- struct{}{}
@ -223,7 +224,7 @@ func (s *Service) TriggerReset(ctx context.Context, _ *emptypb.Empty) (*emptypb.
s.log.Debug("TriggerReset") s.log.Debug("TriggerReset")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
s.triggerReset() s.triggerReset()
}() }()
@ -319,7 +320,7 @@ func (s *Service) ReportBug(ctx context.Context, report *ReportBugRequest) (*emp
}).Debug("ReportBug") }).Debug("ReportBug")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
defer func() { _ = s.SendEvent(NewReportBugFinishedEvent()) }() defer func() { _ = s.SendEvent(NewReportBugFinishedEvent()) }()
@ -348,7 +349,7 @@ func (s *Service) ExportTLSCertificates(_ context.Context, folderPath *wrappersp
s.log.WithField("folderPath", folderPath).Info("ExportTLSCertificates") s.log.WithField("folderPath", folderPath).Info("ExportTLSCertificates")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
cert, key := s.bridge.GetBridgeTLSCert() cert, key := s.bridge.GetBridgeTLSCert()
@ -384,7 +385,7 @@ func (s *Service) Login(ctx context.Context, login *LoginRequest) (*emptypb.Empt
s.log.WithField("username", login.Username).Debug("Login") s.log.WithField("username", login.Username).Debug("Login")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
password, err := base64Decode(login.Password) password, err := base64Decode(login.Password)
if err != nil { if err != nil {
@ -440,7 +441,7 @@ func (s *Service) Login2FA(ctx context.Context, login *LoginRequest) (*emptypb.E
s.log.WithField("username", login.Username).Debug("Login2FA") s.log.WithField("username", login.Username).Debug("Login2FA")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
if s.auth.UID == "" || s.authClient == nil { if s.auth.UID == "" || s.authClient == nil {
s.log.Errorf("Login 2FA: authethication incomplete %s %p", s.auth.UID, s.authClient) s.log.Errorf("Login 2FA: authethication incomplete %s %p", s.auth.UID, s.authClient)
@ -485,7 +486,7 @@ func (s *Service) Login2Passwords(ctx context.Context, login *LoginRequest) (*em
s.log.WithField("username", login.Username).Debug("Login2Passwords") s.log.WithField("username", login.Username).Debug("Login2Passwords")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
password, err := base64Decode(login.Password) password, err := base64Decode(login.Password)
if err != nil { if err != nil {
@ -507,7 +508,7 @@ func (s *Service) LoginAbort(ctx context.Context, loginAbort *LoginAbortRequest)
s.log.WithField("username", loginAbort.Username).Debug("LoginAbort") s.log.WithField("username", loginAbort.Username).Debug("LoginAbort")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
s.loginAbort() s.loginAbort()
}() }()
@ -519,7 +520,7 @@ func (s *Service) CheckUpdate(context.Context, *emptypb.Empty) (*emptypb.Empty,
s.log.Debug("CheckUpdate") s.log.Debug("CheckUpdate")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
updateCh, done := s.bridge.GetEvents( updateCh, done := s.bridge.GetEvents(
events.UpdateAvailable{}, events.UpdateAvailable{},
@ -551,7 +552,7 @@ func (s *Service) InstallUpdate(ctx context.Context, _ *emptypb.Empty) (*emptypb
s.log.Debug("InstallUpdate") s.log.Debug("InstallUpdate")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
safe.RLock(func() { safe.RLock(func() {
s.bridge.InstallUpdate(s.target) s.bridge.InstallUpdate(s.target)
@ -592,7 +593,7 @@ func (s *Service) SetDiskCachePath(ctx context.Context, newPath *wrapperspb.Stri
s.log.WithField("path", newPath.Value).Debug("setDiskCachePath") s.log.WithField("path", newPath.Value).Debug("setDiskCachePath")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
defer func() { defer func() {
_ = s.SendEvent(NewDiskCachePathChangeFinishedEvent()) _ = s.SendEvent(NewDiskCachePathChangeFinishedEvent())
@ -659,7 +660,7 @@ func (s *Service) SetMailServerSettings(_ context.Context, settings *ImapSmtpSet
Debug("SetConnectionMode") Debug("SetConnectionMode")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
defer func() { _ = s.SendEvent(NewChangeMailServerSettingsFinishedEvent()) }() defer func() { _ = s.SendEvent(NewChangeMailServerSettingsFinishedEvent()) }()

View File

@ -20,6 +20,7 @@ package grpc
import ( import (
"context" "context"
"github.com/ProtonMail/gluon/async"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb"
@ -49,7 +50,7 @@ func (s *Service) RunEventStream(request *EventStreamRequest, server Bridge_RunE
// if events occurred before streaming started, they've been queued. Now that the stream channel is available // if events occurred before streaming started, they've been queued. Now that the stream channel is available
// we can flush the queued // we can flush the queued
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
s.eventQueueMutex.Lock() s.eventQueueMutex.Lock()
defer s.eventQueueMutex.Unlock() defer s.eventQueueMutex.Unlock()

View File

@ -20,6 +20,7 @@ package grpc
import ( import (
"context" "context"
"github.com/ProtonMail/gluon/async"
"github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/ProtonMail/proton-bridge/v3/internal/vault"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@ -70,7 +71,7 @@ func (s *Service) SetUserSplitMode(ctx context.Context, splitMode *UserSplitMode
} }
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
defer func() { _ = s.SendEvent(NewUserToggleSplitModeFinishedEvent(splitMode.UserID)) }() defer func() { _ = s.SendEvent(NewUserToggleSplitModeFinishedEvent(splitMode.UserID)) }()
var targetMode vault.AddressMode var targetMode vault.AddressMode
@ -121,7 +122,7 @@ func (s *Service) LogoutUser(ctx context.Context, userID *wrapperspb.StringValue
} }
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
if err := s.bridge.LogoutUser(context.Background(), userID.Value); err != nil { if err := s.bridge.LogoutUser(context.Background(), userID.Value); err != nil {
s.log.WithError(err).Error("Failed to log user out") s.log.WithError(err).Error("Failed to log user out")
@ -135,7 +136,7 @@ func (s *Service) RemoveUser(ctx context.Context, userID *wrapperspb.StringValue
s.log.WithField("UserID", userID.Value).Debug("RemoveUser") s.log.WithField("UserID", userID.Value).Debug("RemoveUser")
go func() { go func() {
defer s.handlePanic() defer async.HandlePanic(s.panicHandler)
// remove preferences // remove preferences
if err := s.bridge.DeleteUser(context.Background(), userID.Value); err != nil { if err := s.bridge.DeleteUser(context.Background(), userID.Value); err != nil {

View File

@ -17,10 +17,6 @@
package grpc package grpc
type CrashHandler interface {
HandlePanic()
}
type Restarter interface { type Restarter interface {
Set(restart, crash bool) Set(restart, crash bool)
AddFlags(flags ...string) AddFlags(flags ...string)

View File

@ -370,7 +370,7 @@ func (user *User) syncMessages(
errorCh := make(chan error, maxParallelDownloads*4) errorCh := make(chan error, maxParallelDownloads*4)
// Go routine in charge of downloading message metadata // Go routine in charge of downloading message metadata
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(downloadCh) defer close(downloadCh)
const MetadataDataPageSize = 150 const MetadataDataPageSize = 150
@ -433,7 +433,7 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "meta-data"}) }, logging.Labels{"sync-stage": "meta-data"})
// Goroutine in charge of downloading and building messages in maxBatchSize batches. // Goroutine in charge of downloading and building messages in maxBatchSize batches.
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(buildCh) defer close(buildCh)
defer close(errorCh) defer close(errorCh)
defer func() { defer func() {
@ -492,7 +492,7 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "download"}) }, logging.Labels{"sync-stage": "download"})
// Goroutine which builds messages after they have been downloaded // Goroutine which builds messages after they have been downloaded
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(flushCh) defer close(flushCh)
defer func() { defer func() {
logrus.Debugf("sync builder exit") logrus.Debugf("sync builder exit")
@ -530,7 +530,7 @@ func (user *User) syncMessages(
}, logging.Labels{"sync-stage": "builder"}) }, logging.Labels{"sync-stage": "builder"})
// Goroutine which converts the messages into updates and builds a waitable structure for progress tracking. // Goroutine which converts the messages into updates and builds a waitable structure for progress tracking.
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) {
defer close(flushUpdateCh) defer close(flushUpdateCh)
defer func() { defer func() {
logrus.Debugf("sync flush exit") logrus.Debugf("sync flush exit")
@ -780,7 +780,7 @@ func (user *User) newAttachmentDownloader(ctx context.Context, client *proton.Cl
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
for i := 0; i < workerCount; i++ { for i := 0; i < workerCount; i++ {
workerCh = make(chan attachmentJob) workerCh = make(chan attachmentJob)
logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{ async.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{
"sync": fmt.Sprintf("att-downloader %v", i), "sync": fmt.Sprintf("att-downloader %v", i),
}) })
} }