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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/src/main/cpp/libzim/archive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ METHOD(jboolean, hasIllustration, jint size) {
GETTER(jlongArray, getIllustrationSizes)

METHOD(jobject, getEntryByPath__Ljava_lang_String_2, jstring path) {
return BUILD_WRAPPER("org/kiwix/libzim/Entry", THIS->getEntryByPath(TO_C(path)));
return BUILD_WRAPPER("org/kiwix/libzim/Entry", SAFE_THIS->getEntryByPath(TO_C(path)));
} CATCH_EXCEPTION(nullptr)

METHOD(jobject, getEntryByPath__I, jint index) {
Expand Down
13 changes: 13 additions & 0 deletions lib/src/main/cpp/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@

#define THIS getPtr<NATIVE_TYPE>(env, thisObj)

#define SAFE_THIS \
({ \
auto ptr = getPtr<NATIVE_TYPE>(env, thisObj); \
if (!ptr) { \
throwException(env, "java/lang/IllegalStateException", "The native object has already been disposed."); \
return nullptr; \
} \
ptr; \
})
Comment on lines +31 to +38
Copy link
Collaborator

Choose a reason for hiding this comment

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

I can't see how this could work in the pre-C++-14 language standard that I am more or less familiar with. SAFE_THIS has to be an expression but it doesn't seem to expand to code that can be considered an expression according to the language specification. I tried to quickly skim through https://en.cppreference.com/w/cpp/language/expressions but couldn't find anything that allows to consider this code valid in modern c++.

In other words, I am puzzled how this code compiles (in the context of the change in lib/src/main/cpp/libzim/archive.cpp).

Copy link
Collaborator Author

@MohitMaliFtechiz MohitMaliFtechiz Jan 18, 2025

Choose a reason for hiding this comment

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

@veloman-yunkan This code is made by @mgautierfr, he can better explain this, and i am not very much familiar with C++.

Copy link
Member

Choose a reason for hiding this comment

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

I think that @veloman-yunkan understand how it works :)

#define FOO BAR make every instance of FOO literally replaced by BAR.

So something like THIS->getEntryByPath(...) is replaced by getPtr<NATIVE_TYPE>(env, thisObj)->getEntryByPath(...). And it compiles because getPtr is a function returning a pointer.

With your define of SAFE_THIS we have SAFE_THIS->getEntryByPath(...) replaced by:

 ({ 
        auto ptr = getPtr<NATIVE_TYPE>(env, thisObj); 
        if (!ptr) { 
            throwException(env, "java/lang/IllegalStateException", "The native object has already been disposed."); 
            return nullptr; 
        } 
        ptr; 
    })->getEntryByPath(...)

And, as @veloman-yunkan, I don't know how this code can be compiled.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

With your define of SAFE_THIS we have SAFE_THIS->getEntryByPath(...) replaced by:

@mgautierfr SAFE_THIS also uses the getPtr<NATIVE_TYPE>(env, thisObj) to get the pointer, and if this method returns the nullptr it throws the error which will be caught in the archive.cpp.

METHOD(jobject, getEntryByPath__Ljava_lang_String_2, jstring path) {
  return BUILD_WRAPPER("org/kiwix/libzim/Entry", SAFE_THIS->getEntryByPath(TO_C(path)));
} CATCH_EXCEPTION(nullptr)

Also, in the archive.cpp SAFE_THIS returns the archive.

Screenshot from 2025-01-21 17-41-04

I think that's why this code was compiled without any error.


#define METHOD0(retType, name) \
JNIEXPORT retType JNICALL BUILD_METHOD(TYPENAME, name) ( \
JNIEnv* env, jobject thisObj) try
Expand Down Expand Up @@ -59,4 +69,7 @@ catch(const zim::ZimFileFormatError& e) { \
} catch(const std::exception& e) { \
throwException(env, "java/lang/Exception", e.what()); \
return RET; \
} catch(...) { \
throwException(env, "java/lang/Error", "Unknown native exception occurred."); \
return RET; \
}
3 changes: 3 additions & 0 deletions lib/src/main/cpp/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ shared_ptr<T> getPtr(JNIEnv* env, jobject thisObj, const char* handleName = "nat
jclass thisClass = env->GetObjectClass(thisObj);
jfieldID fidNumber = env->GetFieldID(thisClass, handleName, "J");
auto handle = reinterpret_cast<shared_ptr<T>*>(env->GetLongField(thisObj, fidNumber));
if (handle == nullptr) {
return nullptr;
}
return *handle;
}
#define GET_PTR(NATIVE_TYPE) getPtr<NATIVE_TYPE>(env, thisObj)
Expand Down
Loading