Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for goroutines to finish when firing a change to an app preferences #2246

Merged
merged 7 commits into from May 24, 2021

Conversation

s77rt
Copy link
Contributor

@s77rt s77rt commented May 15, 2021

Description:

Mainly there was two problems:

  • the first and probably the main bug is that sometimes the app closes too early without waiting for the goroutines that were called in fireChange() and one of those goroutines is the one that calls save() an easy fix was to implement the sync.WaitGroup functionality which i expected to work just fine, yet it didn't due to
  • the second issue which was a misuse of the lockers, in lines 70 and 71 are using Lock() and after that there are goroutines that are expected to read the same struct, well they won't be able to because Lock() only allows one goroutine (read/write) at a time and in fact the goroutines functions that were thought are being executed were actually not, they were just in stuck position waiting for the fireChange() to return (and to trigger it's defer function to Unlock()) so all those go l() were only waiting for fireChange() to return then get executed, well after the fix (1) the function will never return because it's waiting for the goroutines functions which will never work either because they are waiting for fireChange() ,,, deadlock ; the fix was pretty clear is to use RLock() instead of Lock() that way, where multiple goroutines can read(but not write) the struct and the fireChange() will only returns after all the goroutines are done and only after that the app will close

Fixes #2241

Checklist:

  • Tests included.
  • Lint and formatter run with no errors.
  • Tests all pass. (except TestFileIcon(?))

@Jacalz
Copy link
Member

Jacalz commented May 15, 2021

Just a minor thought not related to the contents. Can you please name the title of the PR (this and in the future) to what it does and not just what it fixes? It is very hard to glance over numbers and remember what it does.

Copy link
Member

@Jacalz Jacalz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some small suggestions.

internal/preferences.go Outdated Show resolved Hide resolved
internal/preferences.go Outdated Show resolved Hide resolved
@s77rt s77rt changed the title fixes #2241 Wait for goroutines to finish when firing a change to an app preferences May 15, 2021
@s77rt
Copy link
Contributor Author

s77rt commented May 15, 2021

Just a minor thought not related to the contents. Can you please name the title of the PR (this and in the future) to what it does and not just what it fixes? It is very hard to glance over numbers and remember what it does.

ah sorry for that, the title has been changed

@s77rt s77rt requested a review from Jacalz May 15, 2021 21:02
Jacalz
Jacalz previously approved these changes May 16, 2021
Copy link
Member

@Jacalz Jacalz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. I'll let someone else look on it as well though because I'm away from my computer and can't test it locally.

internal/preferences.go Outdated Show resolved Hide resolved
internal/preferences.go Outdated Show resolved Hide resolved
internal/preferences.go Outdated Show resolved Hide resolved
@andydotxyz
Copy link
Member

andydotxyz commented May 17, 2021

When running this I get deadlocks at runtime in an app that leans heavily on preferences. You can check out https://github.com/fynelabs/notes, when running (after a few edits) I see:

❯ go run .
2021/05/17 09:17:44 Fyne error:  Preferences load error:
2021/05/17 09:17:44   Cause: EOF
2021/05/17 09:17:44   At: /Users/andy/Code/Fyne/fyne/app/preferences.go:70
2021/05/17 09:17:49 Fyne error:  Preferences load error:
2021/05/17 09:17:49   Cause: EOF
2021/05/17 09:17:49   At: /Users/andy/Code/Fyne/fyne/app/preferences.go:70
2021/05/17 09:17:57 Fyne error:  Preferences load error:
2021/05/17 09:17:57   Cause: EOF
2021/05/17 09:17:57   At: /Users/andy/Code/Fyne/fyne/app/preferences.go:70

That was when trying to quit the app, the window disappeared but the process did not exit.
Could it be related? It does not happen every time but I am pretty sure I have not seen it before.

Oh, apologies I should have said earlier, thanks for this - I had wondered if something was incorrect as I realised that sometimes this notes app did not save the final character when making notes and exiting!

waitGroup *sync.WaitGroup to wg *sync.WaitGroup
@s77rt
Copy link
Contributor Author

s77rt commented May 17, 2021

When running this I get deadlocks at runtime in an app that leans heavily on preferences. You can check out https://github.com/fynelabs/notes, when running (after a few edits) I see:

❯ go run .
2021/05/17 09:17:44 Fyne error:  Preferences load error:
2021/05/17 09:17:44   Cause: EOF
2021/05/17 09:17:44   At: /Users/andy/Code/Fyne/fyne/app/preferences.go:70
2021/05/17 09:17:49 Fyne error:  Preferences load error:
2021/05/17 09:17:49   Cause: EOF
2021/05/17 09:17:49   At: /Users/andy/Code/Fyne/fyne/app/preferences.go:70
2021/05/17 09:17:57 Fyne error:  Preferences load error:
2021/05/17 09:17:57   Cause: EOF
2021/05/17 09:17:57   At: /Users/andy/Code/Fyne/fyne/app/preferences.go:70

That was when trying to quit the app, the window disappeared but the process did not exit.
Could it be related? It does not happen every time but I am pretty sure I have not seen it before.

Oh, apologies I should have said earlier, thanks for this - I had wondered if something was incorrect as I realised that sometimes this notes app did not save the final character when making notes and exiting!

I have tried your app and i can't replicate the issue, though sometimes the app does not save the whole string (as you said some chars are left) (some saves are not being saved?)

can you please provide more info about how to replicate this?

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks the code looks good now, but I missed that line of documentation isn't particularly clear.

internal/preferences.go Outdated Show resolved Hide resolved
@s77rt s77rt requested a review from andydotxyz May 21, 2021 12:11
Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice thanks

@Jacalz Jacalz self-requested a review May 24, 2021 11:19
@Jacalz
Copy link
Member

Jacalz commented May 24, 2021

I will have a look at this again later today. Want to make sure that it works for my use cases before we merge it :)

Copy link
Member

@Jacalz Jacalz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works perfectly fine in my testing. Nice work!

@Jacalz Jacalz merged commit 0921509 into fyne-io:develop May 24, 2021
andydotxyz pushed a commit that referenced this pull request Jul 7, 2021
…ces (#2246)

Mainly there was two problems:
- the first and probably the main bug is that sometimes the app closes too early without waiting for the goroutines that were called in [fireChange()](https://github.com/fyne-io/fyne/blob/3814a66f75ff5d24be6fa107f1dfb9c4faa859b1/internal/preferences.go#L69) and one of those goroutines is the one that calls [save()](https://github.com/fyne-io/fyne/blob/3814a66f75ff5d24be6fa107f1dfb9c4faa859b1/app/preferences.go#L35) an easy fix was to implement the sync.WaitGroup functionality which i expected to work just fine, yet it didn't due to
- the second issue which was a misuse of the lockers, in lines [70 and 71](https://github.com/fyne-io/fyne/blob/3814a66f75ff5d24be6fa107f1dfb9c4faa859b1/internal/preferences.go#L70-L71) are using Lock() and after that there are goroutines that are expected to read the same struct, well they won't be able to because Lock() only allows one goroutine (read/write) at a time and in fact the goroutines functions that were thought are being executed were actually not, they were just in stuck position waiting for the fireChange() to return (and to trigger it's defer function to Unlock()) so all those go l() were only waiting for fireChange() to return then get executed, well after the fix (1) the function will never return because it's waiting for the goroutines functions which will never work either because they are waiting for fireChange() ,,, deadlock ; the fix was pretty clear is to use RLock() instead of Lock() that way, where multiple goroutines can read(but not write) the struct and the fireChange() will only returns after all the goroutines are done and only after that the app will close

Fixes #2241
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants