Out of memory crashes/freezing on programmatic OTA updates

Please provide the following:

  1. SDK Version: 44
  2. Platforms(Android/iOS/web/all): Android, iOS
  3. Add the appropriate “Tag” based on what Expo library you have a question on.

A few other points that might be useful context:

  • Using Reanimated 2
  • Ejected our app
  • OTA updates available via both default native implementation and programmatically

We’ve been experiencing issues for a while now where programmatic OTA updates cause sporadic crashes on iOS (~10% of updates). This may also be happening in Android, but those have been harder to reproduce, and if it’s actually been a problem, seems even less common.

Given the nature of expo-updates, these only happen in release builds, making them even harder to debug because not only do we not have a way to easily debug release builds, these crashes have been happening in such a way as to not generate system crash reports: our app will freeze, allowing basic scroll interaction with the particular screen that loaded, but not being able to navigate or interact with the screen in any other useful way, necessitating a force close of the app. The only reason we’ve even discovered that they’re OOM crashes is because Sentry somehow catches these and reports them whenever they happen.

The default behavior of expo-updates works fine: if we never use the API directly, updates work fine on cold starts, without any crashes. However, when we try to programmatically update, i.e. with:

const status = await Updates.checkForUpdateAsync();
if (status.isAvailable) {
  await Updates.fetchUpdateAsync();
  Updates.reloadAsync();
}

is when we experience these crashes. I suspect it’s the actual reloadAsync() itself that’s causing the crashes, since the freezing seems to happen immediately after the restart, and the version numbers we’re seeing reported in Sentry with these OOM crashes are the post-update versions.

Our update bundle size feels rather large at around 7mb, so we’re wondering if that may be problematic, but any insight, feedback, or suggestions on how to dig in or solve this issue would be appreciated!

Bumping this in hopes someone can help!

Debugging memory issues remotely is really difficult for any kind of software. I suspect you will need to use Instruments connected to a device that can reproduce the issue live. Just reloading a lot might trigger the issue.

I don’t recall if Instruments can profile App Store releases of apps but it can profile apps built in release mode (in Xcode, Product => Build For => Profiling).

In case you need to set breakpoints, this is the heart of where reloading happens: expo/EXUpdatesAppController.m at 7d5f352882df092f6665112e2cd0576d27847d54 · expo/expo · GitHub. It calls into react-native:

RCTReloadCommandSetBundleURL(launcher.launchAssetUrl);
RCTTriggerReloadCommandListeners(@"Requested by JavaScript - Updates.reloadAsync()");

A 7 MB bundle isn’t small but it’s also not extraordinarily large. I don’t think it is the cause of your issue, and it’s more likely that a reference to a lot of application state or a view hierarchy is retained across reloads.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.