app: ensure waiting window requests are stopped when a window closes

The Android RegisterFragment method would leak a goroutine if called
after the window was destroyed.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-05-16 11:13:37 +02:00
parent b99151c211
commit e093ea28f7
2 changed files with 20 additions and 7 deletions
+4 -6
View File
@@ -27,10 +27,8 @@ type androidDriver interface {
// and registers it as a Fragment in the Context in which the View was
// created.
func (w *Window) RegisterFragment(del string) {
go func() {
w.driverFuncs <- func() {
d := w.driver.(androidDriver)
d.RegisterFragment(del)
}
}()
w.driverDo(func() {
d := w.driver.(androidDriver)
d.RegisterFragment(del)
})
}
+16 -1
View File
@@ -37,6 +37,8 @@ type Window struct {
invalidates chan struct{}
frames chan *op.Ops
frameAck chan struct{}
// dead is closed when the window is destroyed.
dead chan struct{}
stage system.Stage
animating bool
@@ -96,6 +98,7 @@ func NewWindow(options ...Option) *Window {
frames: make(chan *op.Ops),
frameAck: make(chan struct{}),
driverFuncs: make(chan func()),
dead: make(chan struct{}),
}
w.callbacks.w = w
go w.run(opts)
@@ -188,6 +191,17 @@ func (w *Window) Invalidate() {
}
}
// driverDo calls f as soon as the window has a valid driver attached,
// or does nothing if the window is destroyed while waiting.
func (w *Window) driverDo(f func()) {
go func() {
select {
case w.driverFuncs <- f:
case <-w.dead:
}
}()
}
func (w *Window) updateAnimation() {
animate := false
if w.delayedDraw != nil {
@@ -236,6 +250,7 @@ func (w *Window) destroy(err error) {
// Ack the current event.
w.ack <- struct{}{}
w.out <- system.DestroyEvent{Err: err}
close(w.dead)
for e := range w.in {
w.ack <- struct{}{}
if _, ok := e.(system.DestroyEvent); ok {
@@ -274,7 +289,7 @@ func (w *Window) run(opts *window.Options) {
return
}
for {
var driverFuncs chan func() = nil
var driverFuncs chan func()
if w.driver != nil {
driverFuncs = w.driverFuncs
}