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

Realm.open() hangs on Android #1248

Closed
Damnum opened this issue Aug 25, 2017 · 25 comments · Fixed by #1488
Closed

Realm.open() hangs on Android #1248

Damnum opened this issue Aug 25, 2017 · 25 comments · Fixed by #1488
Assignees
Milestone

Comments

@Damnum
Copy link

Damnum commented Aug 25, 2017

EDIT: This also happens after reloading the emulator on React Native, in a very simple setup (see below #1248 (comment))

Goals

Get an error message when opening a synced realm if server not available or user is offline.

Expected Results

Realm.open() returns a promise that gets rejected with useful error message.

Actual Results

The promise simply stays in pending status indefinitely.

This callback does not get called:

realmConstructor._waitForDownload(config, (error) => {

Hence the promise never returns.

Steps to Reproduce

Run this code after log in with valid user:

const openRealm = (user, url, schema) => {
  return Realm.open({
    sync: { user, url },
    schema,
    schemaVersion: 1
  });
};

Version of Realm and Tooling

  • Realm JS SDK Version: 1.10.3
  • React Native: 0.44.3
  • Which debugger for React Native: None
@Damnum
Copy link
Author

Damnum commented Aug 25, 2017

This only happens on Android, iOS works fine.

@kneth
Copy link
Contributor

kneth commented Aug 28, 2017

@Damnum In the server log, can you see that the user is logged in?
Can you describe your set up (is it a physical device or an emulator? are you connecting to localhost? )?

@kneth kneth added the T-Help label Aug 28, 2017
@Damnum
Copy link
Author

Damnum commented Aug 30, 2017

@kneth by the time I make the Realm.open call, the server is silent. But every 10 minutes I'm getting this server log:

10:21:03 PMinfo
sync: Sync Connection[3174]: Sync connection closed due to being idle
10:21:03 PMinfo
sync: Sync Connection[3174]: Session[2]: Session terminated (session_ident=2).
10:20:52 PMerror
sync: Sync Connection[3180]: Session[2]: Client file already bound in other session (message_type='ident', path='/b07f92ab1e5344d5a256bdc7bbb8de7c/th').
10:20:52 PMinfo
sync: Sync Connection[3178]: Session[2]: Disabled
10:20:52 PMinfo
sync: Sync Connection[3180]: Session[2]: Received: IDENT(server_file_ident=1, client_file_ident=16, client_file_ident_secret=5264769406148302654, scan_server_version=70, scan_client_version=168, latest_server_version=70, latest_server_session_ident=7022817502712743451)
10:20:52 PMinfo
sync: HTTP Connection[3180]: Received: Sync HTTP request(protocol_version=18)
10:20:52 PMinfo
sync: Sync Connection[3180]: Session[2]: Session initiated (session_ident=2).
10:20:52 PMinfo
sync: Sync Connection[3180]: Session[2]: Received: BIND(server_path=/b07f92ab1e5344d5a256bdc7bbb8de7c/th, signed_user_token='...p4j/BfL1oyc1wI4RkJ0RzMAatp7w==', need_file_ident_pair=0)
10:20:52 PMinfo
sync: HTTP Connection[3180]: Connection from 127.0.0.1:56488

I suppose that happens when the user token is refreshed. Same error happens with iOS on the server, though it only hangs on Android.

Happens on Android physical device and simulator. I'm connecting to a server hosted on DigitalOcean. May be related to realm/realm-tasks#397

EDIT: I also setup the realm on a server running on localhost. Still hangs, and the server doesn't even show the error above, so the error is probably not related.

@Damnum Damnum changed the title Realm.open() hangs when server not available Realm.open() hangs on Android Sep 2, 2017
@Damnum
Copy link
Author

Damnum commented Sep 2, 2017

@kneth I tested the exact same configuration on Android (both simulator and device) and iOS, with both localhost and server.

Result: On iOS, everything works as expected.

On Android, function _waitForDownload is never called -> Promise never resolves.

Looks like this function is wrapped into CPP code:

void RealmClass<T>::wait_for_download_completion(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {

Please let me know how to debug this code. Is there a way to print out logs there?

@kneth
Copy link
Contributor

kneth commented Sep 4, 2017

@Damnum Sorry the the late reply. Is it possible for you to contribute a small project which can reproduce the issue?

@Damnum
Copy link
Author

Damnum commented Sep 4, 2017

@kneth I will try. Not sure if it's important but I'm using the Android Java SDK to pre-fill the data in the first place.

I now tried to switch to ROS 2.0.0 rc-2, and realm-js 2.0.0-rc5 (on Android Java site: 4.0.0-BETA2-afe7114-SNAPSHOT). Same result though.

I'm attaching the server log from the moment the client makes the Realm.open call. The client log is silent (just hangs).

server-log.txt

EDIT: I'm also attaching the server log for the (working) Realm.open call on iOS.

server-log-ios-WORKING.txt

Seems like the login takes place in both logs, but the actual synced realm (called shared.realm) is not mentioned in the Android log.

@Damnum
Copy link
Author

Damnum commented Sep 7, 2017

@kneth have you had the chance to look at the logs? I realized that the logs are identical until a point where on iOS, the log says:

4:14:36 PMdebug proxy: attempting to upgrade client.....

After that, the actual download starts.

On Android, the log is silent instead (apart from sending stats). (see time 3:50:13)

@Damnum
Copy link
Author

Damnum commented Sep 10, 2017

@kneth I could reproduce the bug with a very simple setup.

  1. Download the tasks example app: https://github.com/realm-demos/realm-tasks
  2. Install the example ROS on localhost: https://realm.io/docs/get-started/installation/mac/
  3. Run the app as-is (just changelocalhost:9080 to 10.0.2.2:9080 in config.js to make it work on Android): Everything works as expected.
  4. Change the connect function in realm-tasks.js from synchronously opening via new Realm() to asynchronously opening via Realm.open (as recommended in the docs), see code below
  5. Now on Android emulator: First login works. Refresh app. For the following and all subsequent logins, the Realm.open callback hangs.
  6. On iOS, everything works fine even after refreshing multiple times.
function connect(action, username, password, callback) {
  username = username.trim();
  password = password.trim();
  if (username === "") {
    return callback(new Error("Username cannot be empty"));
  } else if (password === "") {
    return callback(new Error("Password cannot be empty"));
  }

  Realm.Sync.User[
    action
  ](config.auth_uri, username, password, (error, user) => {
    if (error) {
      return callback(new Error(error.message));
    } else {
      console.log("Opening realm...");
      Realm.open({
        schema: [Task, TaskList],
        sync: {
          user,
          url: config.db_uri
        },
        path: config.db_path
      }).then(realm => {
        console.log("Realm successfully opened!");
        callback(null, realm);
      });
    }
  });
}

@blagoev
Copy link
Contributor

blagoev commented Sep 11, 2017

Guys, this maybe related to not invoking the promise rejection with settimeout. This maybe the fix for it

3c5f28f

Long story short on RN we have a requirement to use this hack with setTimeout(func, 1) to allow the promise to continue. We have an issue to resolve this properly here #1255 until then this seems like the workaround to use.

You may try cherry picking this fix and testing if the rejection is causing the promise to be stuck

@Damnum
Copy link
Author

Damnum commented Sep 12, 2017

@blagoev I think that will not help in this case. When I debug in this code, the callback given to the _waitForDownload function does not get called:

realmConstructor._waitForDownload(config, (error) => {

That means, line 48 will not even get called at all, so your timeout will never be reached. mE the only way to fix this is inside the wrapping wait_for_download_completion function mentioned above. Or at least improving the logging/error handling there to find out what's causing the issue.

As far as I can tell, the server log is also silent about it.

@ashwinphatak
Copy link
Contributor

I'm able to reproduce the issue and indeed the callback to _waitForDownload never gets called.

@blagoev
Copy link
Contributor

blagoev commented Sep 12, 2017

@Damnum I mentioned this maybe the reason for a hang. If the callback is not called then the hang is in c++ code and we need to debug it to know exactly why. Still a hang in Realm.open will happen in RN if setTimeout is not used for resolve and reject, until we fix the callback issue in RN.

Hopefully when we debug the c++ we will get more details why this happens.

@Damnum
Copy link
Author

Damnum commented Sep 12, 2017

@blagoev do you know how to add debug statements into the c++ code? I tried it with

#include <android/log.h>
...
__android_log_print(ANDROID_LOG_INFO, "JSRealm", "INSIDE wait_for_download_completion");

But no luck so far...

@blagoev
Copy link
Contributor

blagoev commented Sep 12, 2017

Probably the best way is to debug the c++ code in Android Studio, but these __android_log_print should be working as well. Check that this code is picked up when you build the android app. Probably this requires an npm uninstall realm realm-tests && npm install again before build. @ashwinphatak is looking into this as well.

@ashwinphatak
Copy link
Contributor

Added some debugging statements and it appears that the callback to async_wait_for in realm-js/react-native/android/src/main/jni/core/include/realm/sync/client.hpp never gets called the 2nd time onward (after the refresh). That's about as far as I could debug as the implementation of async_wait_for is inside an object file librealm-sync-android-x86.a.

image

image

@Damnum
Copy link
Author

Damnum commented Sep 13, 2017

Thanks for the digging @ashwinphatak ! I'm not really familiar with these native components... do you know if the source code for them is open source?

@Damnum
Copy link
Author

Damnum commented Sep 18, 2017

@ashwinphatak any news on this? This is a real blocker for our project.

@ashwinphatak
Copy link
Contributor

librealm-sync-android-x86.a isn't open source, so we might have to wait for @blagoev to take a look.

@studyroz
Copy link

I'm using [email protected] and [email protected], also facing this issue on Android.

With even simpler setup code:

return Realm.open({
  path: `db.realm`,
  schema
});

@bmunkholm bmunkholm assigned kneth and unassigned ashwinphatak and kneth Oct 9, 2017
@Talor-A
Copy link

Talor-A commented Oct 12, 2017

I'm able to reproduce this as well, on android the first app load works, but reloading JS code makes realm.open never resolve.

@Damnum
Copy link
Author

Damnum commented Oct 15, 2017

@bmunkholm @kneth not sure why this has been marked as "optional"? Failing to open the database is pretty basic stuff because without it you can't do anything else?!

@bmunkholm bmunkholm added this to the RMP 2.0 milestone Oct 15, 2017
@bmunkholm
Copy link
Contributor

@Damnum I can see how that can be confusing :-)
It's not an absolute priority, but a relative priority to the next upcoming release. It means that we will not hold back the release if we can't this fixed before the target date for the release.

@bmunkholm bmunkholm assigned ashwinphatak and unassigned kneth and ashwinphatak Oct 15, 2017
@Damnum
Copy link
Author

Damnum commented Oct 19, 2017

Ok thanks for clarifying, that makes sense!

@blagoev blagoev self-assigned this Oct 23, 2017
@bmunkholm bmunkholm modified the milestones: RMP 2.0, Sprint Oct-30 Oct 25, 2017
@kneth kneth modified the milestones: Sprint Oct-30, Nov-13 Nov 6, 2017
@bmunkholm bmunkholm modified the milestones: Nov-13, Nov-20 Nov 13, 2017
@Talor-A
Copy link

Talor-A commented Nov 21, 2017

is this fix available via npm yet?

@blagoev
Copy link
Contributor

blagoev commented Nov 22, 2017

yes it is

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants