GODT-2160: Prevent double closing of bridge if restart fails

Set imapServer instance to nil once the server is no longer running to
prevent multiple calls to close on shutdown.
This commit is contained in:
Leander Beernaert
2022-11-29 08:38:21 +01:00
parent ae7ae2886f
commit 1c374b59d3
3 changed files with 48 additions and 2 deletions

View File

@ -442,6 +442,30 @@ func TestBridge_FactoryReset(t *testing.T) {
}) })
} }
/* // This test will be enabled in a followup patch
func TestBridge_ChangeCacheDirectory(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) {
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
newCacheDir := t.TempDir()
// Login the user.
userID, err := bridge.LoginFull(ctx, username, password, nil, nil)
require.NoError(t, err)
// The user is now connected.
require.Equal(t, []string{userID}, bridge.GetUserIDs())
require.Equal(t, []string{userID}, getConnectedUserIDs(t, bridge))
// Change directory
_ = bridge.SetGluonDir(ctx, newCacheDir)
// The user is still there
//require.Equal(t, []string{userID}, bridge.GetUserIDs())
//require.Equal(t, []string{userID}, getConnectedUserIDs(t, bridge))
})
})
} */
// withEnv creates the full test environment and runs the tests. // withEnv creates the full test environment and runs the tests.
func withEnv(t *testing.T, tests func(context.Context, *server.Server, *proton.NetCtl, bridge.Locator, []byte), opts ...server.Option) { func withEnv(t *testing.T, tests func(context.Context, *server.Server, *proton.NetCtl, bridge.Locator, []byte), opts ...server.Option) {
server := server.New(opts...) server := server.New(opts...)

View File

@ -47,6 +47,10 @@ const (
) )
func (bridge *Bridge) serveIMAP() error { func (bridge *Bridge) serveIMAP() error {
if bridge.imapServer == nil {
return fmt.Errorf("no imap server instance running")
}
logrus.Info("Starting IMAP server") logrus.Info("Starting IMAP server")
imapListener, err := newListener(bridge.vault.GetIMAPPort(), bridge.vault.GetIMAPSSL(), bridge.tlsConfig) imapListener, err := newListener(bridge.vault.GetIMAPPort(), bridge.vault.GetIMAPSSL(), bridge.tlsConfig)
@ -82,9 +86,12 @@ func (bridge *Bridge) restartIMAP() error {
func (bridge *Bridge) closeIMAP(ctx context.Context) error { func (bridge *Bridge) closeIMAP(ctx context.Context) error {
logrus.Info("Closing IMAP server") logrus.Info("Closing IMAP server")
if bridge.imapServer != nil {
if err := bridge.imapServer.Close(ctx); err != nil { if err := bridge.imapServer.Close(ctx); err != nil {
return fmt.Errorf("failed to close IMAP server: %w", err) return fmt.Errorf("failed to close IMAP server: %w", err)
} }
bridge.imapServer = nil
}
if bridge.imapListener != nil { if bridge.imapListener != nil {
if err := bridge.imapListener.Close(); err != nil { if err := bridge.imapListener.Close(); err != nil {
@ -97,6 +104,10 @@ func (bridge *Bridge) closeIMAP(ctx context.Context) error {
// addIMAPUser connects the given user to gluon. // addIMAPUser connects the given user to gluon.
func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error {
if bridge.imapServer == nil {
return fmt.Errorf("no imap server instance running")
}
imapConn, err := user.NewIMAPConnectors() imapConn, err := user.NewIMAPConnectors()
if err != nil { if err != nil {
return fmt.Errorf("failed to create IMAP connectors: %w", err) return fmt.Errorf("failed to create IMAP connectors: %w", err)
@ -135,6 +146,9 @@ func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error {
// removeIMAPUser disconnects the given user from gluon, optionally also removing its files. // removeIMAPUser disconnects the given user from gluon, optionally also removing its files.
func (bridge *Bridge) removeIMAPUser(ctx context.Context, user *user.User, withData bool) error { func (bridge *Bridge) removeIMAPUser(ctx context.Context, user *user.User, withData bool) error {
if bridge.imapServer == nil {
return fmt.Errorf("no imap server instance running")
}
logrus.WithFields(logrus.Fields{ logrus.WithFields(logrus.Fields{
"userID": user.ID(), "userID": user.ID(),
"withData": withData, "withData": withData,

View File

@ -58,6 +58,10 @@ func (bridge *Bridge) handleUserEvent(ctx context.Context, user *user.User, even
func (bridge *Bridge) handleUserAddressCreated(ctx context.Context, user *user.User, event events.UserAddressCreated) error { func (bridge *Bridge) handleUserAddressCreated(ctx context.Context, user *user.User, event events.UserAddressCreated) error {
if user.GetAddressMode() == vault.SplitMode { if user.GetAddressMode() == vault.SplitMode {
if bridge.imapServer == nil {
return fmt.Errorf("no imap server instance running")
}
gluonID, err := bridge.imapServer.AddUser(ctx, user.NewIMAPConnector(event.AddressID), user.GluonKey()) gluonID, err := bridge.imapServer.AddUser(ctx, user.NewIMAPConnector(event.AddressID), user.GluonKey())
if err != nil { if err != nil {
return fmt.Errorf("failed to add user to IMAP server: %w", err) return fmt.Errorf("failed to add user to IMAP server: %w", err)
@ -86,6 +90,10 @@ func (bridge *Bridge) handleUserAddressUpdated(_ context.Context, user *user.Use
func (bridge *Bridge) handleUserAddressDeleted(ctx context.Context, user *user.User, event events.UserAddressDeleted) error { func (bridge *Bridge) handleUserAddressDeleted(ctx context.Context, user *user.User, event events.UserAddressDeleted) error {
if user.GetAddressMode() == vault.SplitMode { if user.GetAddressMode() == vault.SplitMode {
if bridge.imapServer == nil {
return fmt.Errorf("no imap server instance running")
}
gluonID, ok := user.GetGluonID(event.AddressID) gluonID, ok := user.GetGluonID(event.AddressID)
if !ok { if !ok {
return fmt.Errorf("gluon ID not found for address %s", event.AddressID) return fmt.Errorf("gluon ID not found for address %s", event.AddressID)