Skip to content

Commit 175db1c

Browse files
committed
pgwire: use defer to unlock lastLoginUpdater mutex
This makes the code resilient to panics. Release note: None
1 parent ac53685 commit 175db1c

File tree

1 file changed

+24
-15
lines changed

1 file changed

+24
-15
lines changed

pkg/sql/pgwire/last_login_updater.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,23 @@ func (u *lastLoginUpdater) updateLastLoginTime(ctx context.Context, dbUser usern
106106
func(ctx context.Context) (interface{}, error) {
107107
// The leader adds itself to pending users, and processes all
108108
// pending updates.
109-
u.mu.Lock()
110-
u.mu.pendingUsers[dbUser] = struct{}{}
111-
u.mu.Unlock()
109+
func() {
110+
u.mu.Lock()
111+
defer u.mu.Unlock()
112+
u.mu.pendingUsers[dbUser] = struct{}{}
113+
}()
112114
return nil, u.processPendingUpdates(ctx)
113115
})
114116

115-
// Add this user to the pending set if not the leader,
117+
// Add this user to the pending set if not the leader. This causes the user
118+
// to be processed the next time a singleflight begins, which means the
119+
// recorded estimated_last_login_time will be approximate.
116120
if !leader {
117-
u.mu.Lock()
118-
u.mu.pendingUsers[dbUser] = struct{}{}
119-
u.mu.Unlock()
121+
func() {
122+
u.mu.Lock()
123+
defer u.mu.Unlock()
124+
u.mu.pendingUsers[dbUser] = struct{}{}
125+
}()
120126
} else {
121127
// Leader waits for the result in an async task to avoid blocking authentication
122128
if err := u.execCfg.Stopper.RunAsyncTask(ctx, "wait_last_login_update", func(ctx context.Context) {
@@ -132,14 +138,17 @@ func (u *lastLoginUpdater) updateLastLoginTime(ctx context.Context, dbUser usern
132138

133139
// processPendingUpdates processes all users in the pending set and clears it.
134140
func (u *lastLoginUpdater) processPendingUpdates(ctx context.Context) error {
135-
u.mu.Lock()
136-
users := make([]username.SQLUsername, 0, len(u.mu.pendingUsers))
137-
for user := range u.mu.pendingUsers {
138-
users = append(users, user)
139-
}
140-
// Clear the pending users set.
141-
u.mu.pendingUsers = make(map[username.SQLUsername]struct{})
142-
u.mu.Unlock()
141+
var users []username.SQLUsername
142+
func() {
143+
u.mu.Lock()
144+
defer u.mu.Unlock()
145+
users = make([]username.SQLUsername, 0, len(u.mu.pendingUsers))
146+
for user := range u.mu.pendingUsers {
147+
users = append(users, user)
148+
}
149+
// Clear the pending users set.
150+
u.mu.pendingUsers = make(map[username.SQLUsername]struct{})
151+
}()
143152

144153
if len(users) == 0 {
145154
return nil

0 commit comments

Comments
 (0)