Skip to content

Serial Executor hangs on Android 9 #84

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

Closed
wfilleman opened this issue Apr 17, 2019 · 8 comments
Closed

Serial Executor hangs on Android 9 #84

wfilleman opened this issue Apr 17, 2019 · 8 comments
Assignees
Labels
bug Something isn't working platform: Android This is Android specific

Comments

@wfilleman
Copy link

Current behavior

I'm upgrading my RN app from 0.56 to 0.59.3 and decided to move back to the community AsyncStorage solution. The problem I'm running into is that the serial Executor is getting jammed up processing getKey requests after about the 3rd request for a getKey. The result is in the JS side, the Promise never returns and locks up the app.

Expected behavior

The Serial Executor in use by the AsyncStorage solution would process the AsyncStorage request or fail but not go into a locked up state.

Repro steps

In my RN app, I have 4 AsyncStorage getKey requests during startup which all happen in succession. I've never seen the 4th request return. Sometimes I'll see requests 1-3 return before it hangs on the 4th. This happens on the Simulator and on the device. I've only tested on Android 9 sim and Pixel 2 Android 9.

To point to the Serial Executor as the problem, I removed all references to the Serial Executor in the AsyncStorage code base and just let the SQL Lite requests run on the main thread and it works perfectly.

Environment

  • Async Storage version: 1.3.3
  • React-Native version: 0.59.3
  • Platform tested: Android 9 sim and device (iOS sim and device works great)
@tido64 tido64 added bug Something isn't working platform: Android This is Android specific labels Apr 18, 2019
@krizzu
Copy link
Member

krizzu commented Apr 18, 2019

@wfilleman Hey,

Thanks for reporting this. This is interesting case, seems like serial executor chokes on multiple calls. Did you try it on other Android versions (before Pie)?
And by I have 4 AsyncStorage getKey requests during startup getKey you mean getItem right?

thanks.

@wfilleman
Copy link
Author

Hi @krizzu ,

I just tried this on Android 8 emulator and saw the same lockup results. And yes, thank you, I meant getItem.

Wes

@krizzu krizzu self-assigned this Apr 23, 2019
@krizzu
Copy link
Member

krizzu commented Apr 23, 2019

@wfilleman

I've tried to replicate situation like you mention. I had 4 consequent getItem requests, but every time I'm able to retrieve and save a value, using promises and callbacks.

Can you provide some repro steps that's allow me to have a look? Is there a chance that some of your getItem throws and you're not handling it? (meaning rest of them are not called).

thanks.

@theolavaux
Copy link

theolavaux commented Apr 24, 2019

I've got the exact same problem, here is my implementation, inside a componentDidMount.

  async componentDidMount() {
    const { tryLogin: loginFromFirstScreen } = this.props

    try {
      const sessionToken = await AsyncStorage.getItem('@PicStore:token')

      if (sessionToken) {
        loginFromFirstScreen('', '', sessionToken)
      }
    } catch (error) {
      console.log(
        `Error while reading from async storage ${error.name}: ${error.message}`
      )
    }
  }

Tested on Android Pie (One Plus 6T).
I start getting the Maximum call stack size exceeded error.

@wfilleman
Copy link
Author

wfilleman commented Apr 24, 2019

Hi @krizzu, similar to @theolavaux my implementation is very simple:

export async function loadAllAccounts() {
  console.log('loadAllAccounts');
  const accounts = (await AsyncStorage.getItem('Accounts')) || '{}';
  console.log('AsyncStorage Returned');
  store.setters.setAllAccounts(JSON.parse(accounts));
}

The logging is there so I can track when AsyncStorage returns and when it gets lost on the native side. The caller's "catch" is never executed. When I debugged this on the native side, the serial executor is hung up. It never executes and never throws an error.

Something I'm not sure how to capture or show is I'm also using Parse and Parse Server. The Parse client uses AsyncStorage as well and is actively trying to retrieve values from AsyncStorage in parallel to the rest of my RN app starting up as part of the Parse Client SDK internals. So, for sure, there are parallel requests to AsyncStorage happening and not just a clean promise chain of gets.

Wes

@krizzu krizzu added LEGACY and removed LEGACY labels Jun 18, 2019
@krizzu
Copy link
Member

krizzu commented Jul 4, 2019

I'm going to keep in mind that issue while improving implementation for v2.
Adding this to refs in #133

@krizzu krizzu closed this as completed Jul 4, 2019
@krizzu krizzu mentioned this issue Jul 4, 2019
4 tasks
@wfilleman
Copy link
Author

@krizzu FYI the new AsyncStorage_dedicatedExecutor=true in gradle.properties with AsyncStorage 1.6.1 seems to have fixed this issue I was experiencing on Android. Thank you for making this an option!

https://github.com/react-native-community/async-storage/blob/LEGACY/docs/advanced/DedicatedExecutor.md

@krizzu
Copy link
Member

krizzu commented Aug 5, 2019

Glad you found that useful :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working platform: Android This is Android specific
Projects
None yet
Development

No branches or pull requests

4 participants