fix(daemon): read the client theme under the pane lock when theming a new pane
- commit
- 3af150874d24681b653c4a03c9b5edd37ebc9d40
- author
- brice · · 2026-10-08 09:31 UTC
- committer
- brice · · 2026-10-08 09:31 UTC
- parent
- ad96dc0
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
2 files · +10 -7
M internal/usecase/daemon/floating_spare.go +9 -3
| @@ -160,10 +160,16 @@ func (d *Daemon) applySessionThemeToPane(sess *session, p *pane) { | |||
| 160 | 160 | if len(attachments) == 0 { | |
| 161 | 161 | return | |
| 162 | 162 | } | |
| 163 | - | t := d.effectiveTheme(attachments[0].getClientTheme()) | |
| 163 | + | applyClientThemeToPane(d, attachments[0], p) | |
| 164 | + | } | |
| 165 | + | ||
| 166 | + | // applyClientThemeToPane reads ac's theme while holding p.mu, so a concurrent | |
| 167 | + | // theme application either is seen here or writes the pane after it; a stale | |
| 168 | + | // theme can never overwrite a newer one. ac.themeMu is a leaf lock. | |
| 169 | + | func applyClientThemeToPane(d *Daemon, ac *attachedClient, p *pane) { | |
| 164 | 170 | p.mu.Lock() | |
| 165 | - | applyPaneThemeLocked(p, t, false) | |
| 166 | - | p.mu.Unlock() | |
| 171 | + | defer p.mu.Unlock() | |
| 172 | + | applyPaneThemeLocked(p, d.effectiveTheme(ac.getClientTheme()), false) | |
| 167 | 173 | } | |
| 168 | 174 | ||
| 169 | 175 | // floatingSparePane returns the session's unclaimed spare pane, if any. | |
| @@ -160,10 +160,16 @@ func (d *Daemon) applySessionThemeToPane(sess *session, p *pane) { | |||||
| 160 | if len(attachments) == 0 { | 160 | if len(attachments) == 0 { | ||
| 161 | return | 161 | return | ||
| 162 | } | 162 | } | ||
| 163 | - | t := d.effectiveTheme(attachments[0].getClientTheme()) | 163 | + | applyClientThemeToPane(d, attachments[0], p) |
| 164 | + | } | |||
| 165 | + | ||||
| 166 | + | // applyClientThemeToPane reads ac's theme while holding p.mu, so a concurrent | |||
| 167 | + | // theme application either is seen here or writes the pane after it; a stale | |||
| 168 | + | // theme can never overwrite a newer one. ac.themeMu is a leaf lock. | |||
| 169 | + | func applyClientThemeToPane(d *Daemon, ac *attachedClient, p *pane) { | |||
| 164 | p.mu.Lock() | 170 | p.mu.Lock() | ||
| 165 | - | applyPaneThemeLocked(p, t, false) | 171 | + | defer p.mu.Unlock() |
| 166 | - | p.mu.Unlock() | 172 | + | applyPaneThemeLocked(p, d.effectiveTheme(ac.getClientTheme()), false) |
| 167 | } | 173 | } | ||
| 168 | 174 | ||||
| 169 | // floatingSparePane returns the session's unclaimed spare pane, if any. | 175 | // floatingSparePane returns the session's unclaimed spare pane, if any. | ||
M internal/usecase/daemon/session.go +1 -4
| @@ -726,14 +726,11 @@ func (d *Daemon) createTabForAttachment(sess *session, ac *attachedClient, _ dom | |||
| 726 | 726 | themeClient = attachments[0] | |
| 727 | 727 | } | |
| 728 | 728 | if themeClient != nil { | |
| 729 | - | t := d.effectiveTheme(themeClient.getClientTheme()) | |
| 730 | 729 | tb.mu.Lock() | |
| 731 | 730 | p := tb.focusedPane() | |
| 732 | 731 | tb.mu.Unlock() | |
| 733 | 732 | if p != nil { | |
| 734 | - | p.mu.Lock() | |
| 735 | - | applyPaneThemeLocked(p, t, false) | |
| 736 | - | p.mu.Unlock() | |
| 733 | + | applyClientThemeToPane(d, themeClient, p) | |
| 737 | 734 | } | |
| 738 | 735 | } | |
| 739 | 736 | d.mu.Lock() | |
| @@ -726,14 +726,11 @@ func (d *Daemon) createTabForAttachment(sess *session, ac *attachedClient, _ dom | |||||
| 726 | themeClient = attachments[0] | 726 | themeClient = attachments[0] | ||
| 727 | } | 727 | } | ||
| 728 | if themeClient != nil { | 728 | if themeClient != nil { | ||
| 729 | - | t := d.effectiveTheme(themeClient.getClientTheme()) | |||
| 730 | tb.mu.Lock() | 729 | tb.mu.Lock() | ||
| 731 | p := tb.focusedPane() | 730 | p := tb.focusedPane() | ||
| 732 | tb.mu.Unlock() | 731 | tb.mu.Unlock() | ||
| 733 | if p != nil { | 732 | if p != nil { | ||
| 734 | - | p.mu.Lock() | 733 | + | applyClientThemeToPane(d, themeClient, p) |
| 735 | - | applyPaneThemeLocked(p, t, false) | |||
| 736 | - | p.mu.Unlock() | |||
| 737 | } | 734 | } | ||
| 738 | } | 735 | } | ||
| 739 | d.mu.Lock() | 736 | d.mu.Lock() | ||