fix: protect the dirty flag with an atomic.Bool
SetDirty runs on a Wails call goroutine while the GTK close handler reads the flag, with no synchronisation: an edit landing while a save finished could make the close confirmation unreliable. The spellMu comment already documents the goroutine-per-call convention; the flag that guards against losing work deserves the same care.
This commit is contained in:
1 parent
643adffb12
commit
c0a52a9040
2 files changed
+12
-3
No files matched your search
@@ -7,6 +7,11 @@ version is in the `VERSION` file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- The unsaved-changes marker is now updated atomically: an edit landing while a save
|
||||
finished could make the close confirmation unreliable.
|
||||
|
||||
## [1.4] - 2026-10-15
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
@@ -25,7 +26,10 @@ import (
|
||||
// App is bound to the frontend: every exported method is callable from JS.
|
||||
type App struct {
|
||||
ctx context.Context
|
||||
dirty bool
|
||||
// dirty decides whether closing the window asks for confirmation. It is
|
||||
// written from Wails call goroutines (SetDirty) and read by the GTK
|
||||
// close handler: atomic, like spellMu protects the checker.
|
||||
dirty atomic.Bool
|
||||
initialPath string
|
||||
|
||||
// Wails runs each call on its own goroutine: spelling calls share one
|
||||
@@ -74,7 +78,7 @@ func (a *App) startup(ctx context.Context) {
|
||||
// beforeClose keeps the window open while there are unsaved changes and
|
||||
// lets the frontend ask; it quits again once the user has decided.
|
||||
func (a *App) beforeClose(ctx context.Context) bool {
|
||||
if !a.dirty {
|
||||
if !a.dirty.Load() {
|
||||
return false
|
||||
}
|
||||
runtime.EventsEmit(a.ctx, "confirm-close")
|
||||
@@ -201,7 +205,7 @@ func (a *App) RevisionSet(n int) screenplay.Revision {
|
||||
return r
|
||||
}
|
||||
|
||||
func (a *App) SetDirty(dirty bool) { a.dirty = dirty }
|
||||
func (a *App) SetDirty(dirty bool) { a.dirty.Store(dirty) }
|
||||
|
||||
// dataDir is the XDG data directory (~/.local/share).
|
||||
func dataDir() string {
|
||||
|
||||
Reference in new issue
Block a user