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

Remove ObjectListener inside Callback crashes with SIGSEGV #6427

Open
ppamorim opened this issue Feb 12, 2019 · 10 comments
Open

Remove ObjectListener inside Callback crashes with SIGSEGV #6427

ppamorim opened this issue Feb 12, 2019 · 10 comments

Comments

@ppamorim
Copy link

ppamorim commented Feb 12, 2019

Actual Results

App is crashing during a transaction. Returning error like SIGSEGV (signal SIGSEGV: address access protected (fault address: 0x752ff03e90)) I bet it is a crash on the C++ core. My Realm is encrypted.
I can send a debug APK privately, will this be useful?

List of errors:

Signal: SIGSEGV (signal SIGSEGV: invalid address (fault address: 0x4108f942e508))
Signal: SIGSEGV (signal SIGSEGV: address access protected (fault address: 0x752ff03e90))
Signal: SIGSEGV (signal SIGSEGV: invalid address (fault address: 0x4108f942e508))
lost connection //App closes

screen shot 2019-02-12 at 17 04 25
screen shot 2019-02-12 at 17 03 48

EDIT 1:

I modified the source to have two transactions, like this:

val realm = Realm.getDefaultInstance()
getTask(realm, name)?.let { task ->
  realm.executeTransaction {
    task.type = newType //This works perfectly
  }
  realm.executeTransaction {
    task.mode = null
  }
}
realm.close()

The crash stopped and the change is being committed. Is there any reason why I can't modify two parameters from the object once?

EDIT 2:

I've sent a debug APK to Realm's private email.

Steps & Code to Reproduce

val realm = Realm.getDefaultInstance()
realm.executeTransaction {
  getTask(realm, name)?.let { task ->
    task.type = newType //This works perfectly
    task.mode = null //crash here, mode is optional, setting a non null value doesn't make any difference, if I remove this part of the code the crash stops.
  }
}
realm.close()

EDIT 3:

I confirm that this bug is also happening on version 5.9.0.

EDIT 4:

The location of the error is random, it depends on how many transactions are you doing in a single realm instance, when I call Realm.close() I get Signal: SIGBUS (signal SIGBUS: illegal alignment).

EDIT 5:
The crash is also happening when multidex is disabled.

EDIT 6:
RealmLogger moments before the crash: https://gist.github.com/ppamorim/80768e9882f6dd9a663356deffc872df
I've sent a new APK on the ticket open on Realm Support. #⁠3077
Database size is about 600kb, the crash happens even on fresh install.

EDIT 7:
New logs from tombstone: https://gist.github.com/ppamorim/be83f1891e87e6415c14420dfcf7bae2

Version of Realm and tooling

Realm version(s): 5.9.0, 5.8.0

Realm Sync feature enabled: No

Android Studio version: 3.3

Android Build Tools version:

  • com.android.tools.build:gradle:3.3.0
  • multiDexEnabled true

Gradle version: 5.2.1, 5.1.1, 4.10.2

Which Android version and device(s): 8.0.0 on One Plus 3T

@ppamorim
Copy link
Author

Probably related: realm/realm-core#2944

@taynanbonaldo
Copy link

I was able to reproduce the same problem here. As well as @ppamorim commented, the error seems to be random, occurs in different Realm method calls.

@ppamorim
Copy link
Author

@cmelchior I think I have found the issue. I was modifying a specific object in a async thread with this same object loaded in the main thread with a change listener added. When the async thread finishes (commit the realm changes) I was calling a method on the main thread to remove and re-add the change listener, which caused the error. Removing the change listener stopped the error from happening. Shouldn't the change listener be passive?

@ppamorim
Copy link
Author

@cmelchior I will try to replicate this on a sample app.

@cmelchior
Copy link
Contributor

@ppamorim I assume you are talking about a single object listener, correct?
It should work, but given that the code around handling notifications for single objects are a bit complex I wouldn't be super surprised if we had a bug in there somewhere. Do you perhaps have a code snippet I can take a look at and see if I can reproduce it on my end?

@ppamorim
Copy link
Author

@cmelchior Yes, it's the RealmObjectChangeListener.

@ppamorim
Copy link
Author

ppamorim commented Feb 22, 2019

@cmelchior Here is the reproduction: https://github.com/ppamorim/realm-SIGSEGV-crash
Keep trying compiling it multiple times and uncommenting the lines 45-48 if the crash does not happen. I know, the example is ridiculous but it was the only way I found to simulate it on a example, my app probably was doing the same but in different threads and contexts. All the source is contained on MainActivity.kt.

@cmelchior
Copy link
Contributor

cmelchior commented Feb 22, 2019

@ppamorim Thank you very much for this. I can reproduce the crash.

It happens because you remove the changelistener from inside the changelistener. This should be supported but I guess there is a bug somewhere I have to track down.

If you want to work around it, for now, you can try to remove it from outside the callback, e.g. by doing it in a runOnUiThread():

        foo?.addChangeListener<Foo> { _, _ ->
            runOnUiThread { foo?.removeAllChangeListeners() }
            foo?.addChangeListener<Foo> { _, _ -> }
        }

EDIT: Actually scratch that. I suspect that the above just alters the timing. The reason in your example project is that objects are being GC'ed with active change listeners and somehow we still think they are live when in fact they are not.

@ppamorim
Copy link
Author

ppamorim commented Feb 22, 2019

@cmelchior Thank you, I have implemented states to prevent unnecessary add and remove of change listeners (I am using the addChangeListener with parameter, not a directly lambda on my project). I think I experienced something similar on iOS related to removing change listeners inside a change listener callback, but I am not 100% sure.

@ppamorim
Copy link
Author

@cmelchior I agree with you, preventing any unnecessary update of the variable foo during the execution stops the error from happening. I simply have added a if (foo == null) to check if the variable is already loaded and the problem has stopped. Unfortunately this is not a solution since the reattribution of values can happen anytime for whatever reason.

@cmelchior cmelchior changed the title SIGSEGV (signal SIGSEGV: address access protected (fault address: 0x752ff03e90)) Remove ObjectListener inside Callback crashes with SIGSEGV Mar 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants