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

Fixed the native crash happening on Android. #116

Merged
merged 2 commits into from
Jan 27, 2025

Conversation

MohitMaliFtechiz
Copy link
Collaborator

@MohitMaliFtechiz MohitMaliFtechiz commented Jan 17, 2025

See issue kiwix/kiwix-android#3956

  • The issue on the Android side was a null pointer dereference, meaning that when accessing the getEntryByPath method, the archive object had already been disposed of, which caused the crash.

  • We are correctly handling and disposing of the previous archive and web views for the previously set archive. However, web views load content on their own thread. When we change the ZIM file, we dispose of the previous archive and stop the ongoing web view processes. In certain cases, the web view internally tries to get content via the getEntryByPath method because it takes some time to cancel all the previous calls on the background thread. As a result, the web view attempts to call the method on a disposed archive, which causes the native crash.

  • To fix this, I refactored the getPtr method to throw NativeHandleDisposedException if the archive has already been disposed, and handled this custom error in the CATCH_EXCEPTION macro. Now, instead of crashing the entire program, it correctly throws an error, which is handled by Kiwix.

  • Handling this scenario on the Android side is not feasible since the WebView operates on a separate thread over which we have no control. However, addressing this issue on the java-libkiwix side is a better approach. If an object is already disposed, it should throw an error that can be caught by the caller, instead of crashing the entire program. Handling such errors is the responsibility of the user of java-libkiwix (e.g., Kiwix Android). We are already handling all errors thrown by java-libkiwix in the Kiwix Android app.

The issue sometimes occurs on the CI see https://github.com/kiwix/kiwix-android/actions/runs/12809338048/job/35713951704?pr=4177#step:8:9560

@MohitMaliFtechiz
Copy link
Collaborator Author

@kelson42, @mgautierfr Can you please review the PR and validate the idea? then I will refactore the remaining code.

Copy link

codecov bot commented Jan 17, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.23%. Comparing base (4c6dadb) to head (d7c3899).
Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##               main     #116   +/-   ##
=========================================
  Coverage     93.23%   93.23%           
  Complexity      237      237           
=========================================
  Files            47       47           
  Lines           325      325           
  Branches          3        3           
=========================================
  Hits            303      303           
  Misses           19       19           
  Partials          3        3           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kelson42 kelson42 requested review from veloman-yunkan and mgautierfr and removed request for mgautierfr January 17, 2025 17:37
lib/src/main/cpp/macros.h Outdated Show resolved Hide resolved
lib/src/main/cpp/utils.h Outdated Show resolved Hide resolved
Copy link
Member

@mgautierfr mgautierfr left a comment

Choose a reason for hiding this comment

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

We are correctly handling and disposing of the previous archive and web views for the previously set archive.

I would say that you are not correctly disposing the previous archive if you are disposing it while something is still using it.

However, I understand it can be difficult to do such memory management in a java world where everything is expected to be managed by GC.

I have a clean solution for this problem and it is pr #25. The PR remove the need to call dispose on libzim object (and even remove this method) and make resource automatically clean up when GC destroy the object.

@MohitMaliFtechiz
Copy link
Collaborator Author

I would say that you are not correctly disposing the previous archive if you are disposing it while something is still using it.

@mgautierfr You are right, and I mentioned this thing in the PR description please see point 4(We have done all possible things to remove loading of webView at the Android level).

I have a clean solution for this problem and it is pr #25. The PR remove the need to call dispose on libzim object (and even remove this method) and make resource automatically clean up when GC destroy the object.

Could we complete that PR so we get rid of this error?

@mgautierfr
Copy link
Member

Could we complete that PR so we get rid of this error?

The PR is complete (at least at the time of submission, we may have few merge conflict to fix).
It hasn't been merge because we need an update the minimun sdk version to 33 and it will (was at least, don't know now) drop compatibility with too many "old" android devices.

@MohitMaliFtechiz
Copy link
Collaborator Author

It hasn't been merge because we need an update the minimun sdk version to 33 and it will (was at least, don't know now) drop compatibility with too many "old" android devices.

@mgautierfr I am not in favor of upgrading the minimum SDK version to 33 since it drops the compatibility for most of the devices. Since SDK 33 means Android 13 which is a very new device which is few users using this and the above devices, and most of the users still using the old devices like Android 12, Android 11, etc.

Is there any other alternative to use the new PR without upgrading the minimum SDK version? If currently not, what do you think about my this proposal #116 (comment)?

@mgautierfr
Copy link
Member

Is there any other alternative to use the new PR without upgrading the minimum SDK version? If currently not, what do you think about my this proposal #116 (comment)?

I don't know about other alternative. This is why we are in a stuck situation about #25

Throwing an exception in case the object is already disposed is probably the only solution we have for now. See my comment #116 (comment)

* Improved the `getPtr` method to throw a `NativeHandleDisposedException` when a native object is `nullptr`, updated the `CATCH_EXCEPTION` macro to handle this exception by mapping it to `java.lang.IllegalStateException`, and ensured proper error handling to prevent crashes when accessing disposed objects.
Copy link
Member

@mgautierfr mgautierfr left a comment

Choose a reason for hiding this comment

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

Just a small fix about the message text (I'm picky) but else I think we are good !

lib/src/main/cpp/utils.h Outdated Show resolved Hide resolved
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.

4 participants