From 4e0d820a5ba822409954617c869dba15aad55676 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 22 Jul 2019 09:33:53 +0200 Subject: [PATCH] ui/app: (android) block until DataDir is ready The app data dir is not set until after Go's init functions have run, which means that DataDir is inherently racy. Avoid that race by blocking in DataDir until it is set from Java. In other words, trade a race condition with a deadlock. Signed-off-by: Elias Naur --- ui/app/app.go | 3 +++ ui/app/datadir_android.go | 18 ++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ui/app/app.go b/ui/app/app.go index 499e0d64..57dcb85e 100644 --- a/ui/app/app.go +++ b/ui/app/app.go @@ -121,6 +121,9 @@ func init() { // On desktop systems, DataDir use os.UserConfigDir. // On iOS NSDocumentDirectory is queried. // For Android Context.getFilesDir is used. +// +// BUG: DataDir blocks on Android until init functions +// have completed. func DataDir() (string, error) { return dataDir() } diff --git a/ui/app/datadir_android.go b/ui/app/datadir_android.go index 2e5901d4..0065ad1d 100644 --- a/ui/app/datadir_android.go +++ b/ui/app/datadir_android.go @@ -5,13 +5,23 @@ package app import "C" +import "sync" -var dataDir func() (string, error) +var ( + dataDirOnce sync.Once + dataDirChan = make(chan string, 1) + dataPath string +) + +func dataDir() (string, error) { + dataDirOnce.Do(func() { + dataPath = <-dataDirChan + }) + return dataPath, nil +} //export setDataDir func setDataDir(cdir *C.char, len C.int) { dir := C.GoStringN(cdir, len) - dataDir = func() (string, error) { - return dir, nil - } + dataDirChan <- dir }