diff --git a/service.go b/service.go index c12c156..966a02b 100644 --- a/service.go +++ b/service.go @@ -1076,15 +1076,19 @@ func handleUserDelete(ctx *serviceContext, params []string) error { return fmt.Errorf("provided confirmation token doesn't match user") } - c := ctx.Context + var deleteCtx context.Context = ctx if self { ctx.print(fmt.Sprintf("Goodbye %s, deleting your account. There will be no further confirmation.", username)) - c = context.TODO() + // We can't use ctx here, because it'll be cancelled once we close the + // downstream connection + deleteCtx = context.TODO() } - u.stop() + if err := u.stop(deleteCtx); err != nil { + return fmt.Errorf("failed to stop user: %v", err) + } - if err := ctx.user.srv.db.DeleteUser(c, u.ID); err != nil { + if err := ctx.user.srv.db.DeleteUser(deleteCtx, u.ID); err != nil { return fmt.Errorf("failed to delete user: %v", err) } diff --git a/user.go b/user.go index 6e28da9..9cd699d 100644 --- a/user.go +++ b/user.go @@ -1126,9 +1126,22 @@ func (u *user) updateUser(ctx context.Context, record *database.User) error { return nil } -func (u *user) stop() { - u.events <- eventStop{} - <-u.done +func (u *user) stop(ctx context.Context) error { + select { + case <-u.done: + return nil // already stopped + case u.events <- eventStop{}: + // we've requested to stop, let's wait for the user goroutine to exit + case <-ctx.Done(): + return ctx.Err() + } + + select { + case <-u.done: + return nil + case <-ctx.Done(): + return ctx.Err() + } } func (u *user) hasPersistentMsgStore() bool {