~eliasnaur/gio

6 4

defer

Details
Message ID
<f6cc5d038a05c199cdb755fccbea9e35@evereska.org>
DKIM signature
pass
Download raw message
Hi,

I opened some database connection on android directly in the main, not in the UI goroutine.
I wanted to defer the close of the database directly at the exit of the main, but it seems it is
not really defered, and get called immediately at the moment we defer it.
Is it a normal situation? Should we defer close in the goroutine (and also create the database
connection as well)?
Has someone an explanation for that? I would like to understand it because I guess it might be a design
decision?

Tanguy
Details
Message ID
<BZ47Q3N76YHC.32EXMN99DIASW@testmac>
In-Reply-To
<f6cc5d038a05c199cdb755fccbea9e35@evereska.org> (view parent)
DKIM signature
pass
Download raw message
On Fri Dec 13, 2019 at 9:41 AM Tanguy ⧓ Herrmann wrote:
> Hi,
> 
> I opened some database connection on android directly in the main, not in the UI goroutine.
> I wanted to defer the close of the database directly at the exit of the main, but it seems it is
> not really defered, and get called immediately at the moment we defer it.
> Is it a normal situation? Should we defer close in the goroutine (and also create the database
> connection as well)?
> Has someone an explanation for that? I would like to understand it because I guess it might be a design
> decision?
> 

It's a forced design decision. Go doesn't own the main thread on
Android, the Android SDK does. So app.Main on Android returns
immediately, triggering your defers. See

	https://git.sr.ht/~eliasnaur/gio/tree/master/app/internal/window/os_android.go#L456

and

	https://git.sr.ht/~eliasnaur/gio/tree/master/app/internal/window/runmain.go

for the trick of running main even in c-shared mode.

-- elias
Details
Message ID
<65a2422e8f14456f5d6373ff3d9650bb@evereska.org>
In-Reply-To
<BZ47Q3N76YHC.32EXMN99DIASW@testmac> (view parent)
DKIM signature
pass
Download raw message
> It's a forced design decision. Go doesn't own the main thread on
> Android, the Android SDK does. So app.Main on Android returns
> immediately, triggering your defers.
So, I should really put my full app logic in the goroutine and not directly in the main?
That would work?

> for the trick of running main even in c-shared mode.
I stumbled upon it looking at the app.DataDir() the other day, but it didn't connect as much dot as it does
today for me. It's a pretty nice idea, even if hacky. So at least the code is somewhat similar between
platforms (even though less Go-idiomatic).

Thanks!
Gregory Pomerantz
Details
Message ID
<9f5a6906-d794-4eff-8f79-8f38e8794d0b@wow.st>
In-Reply-To
<65a2422e8f14456f5d6373ff3d9650bb@evereska.org> (view parent)
DKIM signature
pass
Download raw message
On 12/13/19 5:49 AM, Tanguy ⧓ Herrmann wrote:

>> It's a forced design decision. Go doesn't own the main thread on
>> Android, the Android SDK does. So app.Main on Android returns
>> immediately, triggering your defers.
> So, I should really put my full app logic in the goroutine and not directly in the main?
> That would work?

I was wondering about this too. This should be clarified in the docs for 
gioui.org/app, which currently says:

     Because Main is also blocking, the event loop of a Window must run 
in a goroutine.

Should we change it to say "is also blocking on some platforms"?
Details
Message ID
<BZ4GMAQXZ5YJ.FO0QY4102MRZ@toolbox>
In-Reply-To
<9f5a6906-d794-4eff-8f79-8f38e8794d0b@wow.st> (view parent)
DKIM signature
pass
Download raw message
On Fri Dec 13, 2019 at 9:13 AM Gregory Pomerantz wrote:
> On 12/13/19 5:49 AM, Tanguy ⧓ Herrmann wrote:
> 
> >> It's a forced design decision. Go doesn't own the main thread on
> >> Android, the Android SDK does. So app.Main on Android returns
> >> immediately, triggering your defers.
> > So, I should really put my full app logic in the goroutine and not directly in the main?
> > That would work?

As long as you're doing the initialization before app.Main, it doesn't matter
where you do it.

> 
> I was wondering about this too. This should be clarified in the docs for 
> gioui.org/app, which currently says:
> 
>      Because Main is also blocking, the event loop of a Window must run 
> in a goroutine.
> 
> Should we change it to say "is also blocking on some platforms"?

SGTM.
Details
Message ID
<81896790a4bbc1c3da95699c3d1b9cde@evereska.org>
In-Reply-To
<BZ4GMAQXZ5YJ.FO0QY4102MRZ@toolbox> (view parent)
DKIM signature
pass
Download raw message
December 13, 2019 6:17 PM, "Elias Naur" <mail@eliasnaur.com> wrote:

> As long as you're doing the initialization before app.Main, it doesn't matter
> where you do it.

I tested by defering from the app goroutine. On android, it actually doesn't "matter" since when leaving the app by going on the home, or pressing BACK button, the goroutine is not interrupted, and thus, the defer is not called either.
And if you force kill the app, the defer is also not called.
I don't know what it means in terms of transactions/data corruptions, etc. Like if we force kill the app in the middle of a long database interaction, could it be a problem? And if so, how could we handle it gracefully?

On desktop, the defer is well called when we close the window. So it's less of an issue if intercept the os/signal. I don't know for Android though.
Details
Message ID
<BZ51CQDVFBC8.JLKELYHFB06J@testmac>
In-Reply-To
<81896790a4bbc1c3da95699c3d1b9cde@evereska.org> (view parent)
DKIM signature
pass
Download raw message
On Sat Dec 14, 2019 at 1:00 AM  wrote:
> December 13, 2019 6:17 PM, "Elias Naur" <mail@eliasnaur.com> wrote:
> 
> > As long as you're doing the initialization before app.Main, it doesn't matter
> > where you do it.
> 
> I tested by defering from the app goroutine. On android, it actually doesn't "matter" since when leaving the app by going on the home, or pressing BACK button, the goroutine is not interrupted, and thus, the defer is not called either.
> And if you force kill the app, the defer is also not called.
> I don't know what it means in terms of transactions/data corruptions, etc. Like if we force kill the app in the middle of a long database interaction, could it be a problem? And if so, how could we handle it gracefully?
> 
> On desktop, the defer is well called when we close the window. So it's less of an issue if intercept the os/signal. I don't know for Android though.

Even on desktop you can't be sure the window is closed gracefully. The
power might go off, or an OS issue might prevent it from closing cleanly,
someone can send your process a SIGKILL and so on.

Instead of relying on clean exits, most (all?) databases are designed to
recover from sudden failures. For example, transaction are usually
atomic, even in the presence of sudden exit or system failures (but not
always disk failures).

See also https://en.wikipedia.org/wiki/Crash-only_software that takes
the database design to the extrame and suggests programs have *no*
cleanup code.

However, there is a onSaveInstanceState on Android designed for
checkpointing state before a potential killing of your app. This is
where you typically save UI state such as the current screen, text
fields content and so on.

Gio doesn't give you access to onSaveInstanceState, but could be
modified to do so. I think the existing io/system.Command event is the
best fit for the feature.

-- elias