diff --git a/CHANGES.md b/CHANGES.md
index c21d491ccf..60f65abcc9 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,7 @@ Bug Fixes
---------
* [#925](https://github.com/java-native-access/jna/issues/925): Optimize `Structure#validate` and prevent `ArrayIndexOutOfBoundsException` in `SAFEARRAY#read` for zero dimensions - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#958](https://github.com/java-native-access/jna/issues/958): Update for PR 863: Old toolchains produce binaries without hard-/softfloat markers. Rasbian is missinng the markers and the oracle JDK is also affected. For hardfloat detection now also the Arm EABI section is also considered - [@matthiasblaesing](https://github.com/matthiasblaesing).
+* [#974](https://github.com/java-native-access/jna/issues/974): If the callback code failed to attach to the JVM, this lead to a segfault. The success of attaching to the JVM was checked to late and an invalid `JNIEnv` pointer was used to access the JVM - [@matthiasblaesing](https://github.com/matthiasblaesing).
Release 4.5.1
=============
diff --git a/build.xml b/build.xml
index d6b612e9a2..f763f02ec1 100644
--- a/build.xml
+++ b/build.xml
@@ -69,7 +69,7 @@
-
+
diff --git a/lib/native/aix-ppc.jar b/lib/native/aix-ppc.jar
index f6be141f54..d59e910edc 100644
Binary files a/lib/native/aix-ppc.jar and b/lib/native/aix-ppc.jar differ
diff --git a/lib/native/aix-ppc64.jar b/lib/native/aix-ppc64.jar
index 01a378bdb1..4995ce9cba 100644
Binary files a/lib/native/aix-ppc64.jar and b/lib/native/aix-ppc64.jar differ
diff --git a/lib/native/android-aarch64.jar b/lib/native/android-aarch64.jar
index 83438eaa14..96c2d9f570 100644
Binary files a/lib/native/android-aarch64.jar and b/lib/native/android-aarch64.jar differ
diff --git a/lib/native/android-arm.jar b/lib/native/android-arm.jar
index d78f1611e2..20d21ae5a9 100755
Binary files a/lib/native/android-arm.jar and b/lib/native/android-arm.jar differ
diff --git a/lib/native/android-armv7.jar b/lib/native/android-armv7.jar
index ad98394186..8f537179ac 100644
Binary files a/lib/native/android-armv7.jar and b/lib/native/android-armv7.jar differ
diff --git a/lib/native/android-mips.jar b/lib/native/android-mips.jar
index 7fd7ee799f..5b20b67f20 100644
Binary files a/lib/native/android-mips.jar and b/lib/native/android-mips.jar differ
diff --git a/lib/native/android-mips64.jar b/lib/native/android-mips64.jar
index 6b2b561cea..2cafc732aa 100644
Binary files a/lib/native/android-mips64.jar and b/lib/native/android-mips64.jar differ
diff --git a/lib/native/android-x86-64.jar b/lib/native/android-x86-64.jar
index dbc1c7f09c..0e715a4947 100644
Binary files a/lib/native/android-x86-64.jar and b/lib/native/android-x86-64.jar differ
diff --git a/lib/native/android-x86.jar b/lib/native/android-x86.jar
index 5ebf1f0a7c..c3d802fc4b 100755
Binary files a/lib/native/android-x86.jar and b/lib/native/android-x86.jar differ
diff --git a/lib/native/darwin.jar b/lib/native/darwin.jar
index d8c06c21b2..77a2d35cb2 100644
Binary files a/lib/native/darwin.jar and b/lib/native/darwin.jar differ
diff --git a/lib/native/freebsd-x86-64.jar b/lib/native/freebsd-x86-64.jar
index c58184476c..9f2a2cca09 100755
Binary files a/lib/native/freebsd-x86-64.jar and b/lib/native/freebsd-x86-64.jar differ
diff --git a/lib/native/freebsd-x86.jar b/lib/native/freebsd-x86.jar
index b04bbb0b97..eb5f0daa02 100755
Binary files a/lib/native/freebsd-x86.jar and b/lib/native/freebsd-x86.jar differ
diff --git a/lib/native/linux-aarch64.jar b/lib/native/linux-aarch64.jar
index 3cf08eb1eb..cb84490565 100644
Binary files a/lib/native/linux-aarch64.jar and b/lib/native/linux-aarch64.jar differ
diff --git a/lib/native/linux-arm.jar b/lib/native/linux-arm.jar
index 6dd1afbb47..5afdd38512 100755
Binary files a/lib/native/linux-arm.jar and b/lib/native/linux-arm.jar differ
diff --git a/lib/native/linux-armel.jar b/lib/native/linux-armel.jar
index 70d9b1ab35..174bf98f77 100644
Binary files a/lib/native/linux-armel.jar and b/lib/native/linux-armel.jar differ
diff --git a/lib/native/linux-mips64el.jar b/lib/native/linux-mips64el.jar
index 9202631078..deb0b92ffd 100644
Binary files a/lib/native/linux-mips64el.jar and b/lib/native/linux-mips64el.jar differ
diff --git a/lib/native/linux-ppc.jar b/lib/native/linux-ppc.jar
index c6890dc78c..5667f59c91 100755
Binary files a/lib/native/linux-ppc.jar and b/lib/native/linux-ppc.jar differ
diff --git a/lib/native/linux-ppc64le.jar b/lib/native/linux-ppc64le.jar
index 2201978865..ae4d3f5561 100644
Binary files a/lib/native/linux-ppc64le.jar and b/lib/native/linux-ppc64le.jar differ
diff --git a/lib/native/linux-s390x.jar b/lib/native/linux-s390x.jar
index 1b4d6fa78f..102fc5044d 100644
Binary files a/lib/native/linux-s390x.jar and b/lib/native/linux-s390x.jar differ
diff --git a/lib/native/linux-x86-64.jar b/lib/native/linux-x86-64.jar
index a4ec3c1660..b99f49fc6e 100644
Binary files a/lib/native/linux-x86-64.jar and b/lib/native/linux-x86-64.jar differ
diff --git a/lib/native/linux-x86.jar b/lib/native/linux-x86.jar
index 58296a8a88..4dc786fca5 100755
Binary files a/lib/native/linux-x86.jar and b/lib/native/linux-x86.jar differ
diff --git a/lib/native/openbsd-x86-64.jar b/lib/native/openbsd-x86-64.jar
index 414bcbbd9b..ddd6d316fc 100755
Binary files a/lib/native/openbsd-x86-64.jar and b/lib/native/openbsd-x86-64.jar differ
diff --git a/lib/native/openbsd-x86.jar b/lib/native/openbsd-x86.jar
index 0e6226e5ea..e9d7a289b8 100755
Binary files a/lib/native/openbsd-x86.jar and b/lib/native/openbsd-x86.jar differ
diff --git a/lib/native/sunos-sparc.jar b/lib/native/sunos-sparc.jar
index 71c510e17e..5798c7f213 100644
Binary files a/lib/native/sunos-sparc.jar and b/lib/native/sunos-sparc.jar differ
diff --git a/lib/native/sunos-sparcv9.jar b/lib/native/sunos-sparcv9.jar
index 4b6303ca8b..e508bf8e7e 100755
Binary files a/lib/native/sunos-sparcv9.jar and b/lib/native/sunos-sparcv9.jar differ
diff --git a/lib/native/sunos-x86-64.jar b/lib/native/sunos-x86-64.jar
index e995162bb7..ac43ba891b 100755
Binary files a/lib/native/sunos-x86-64.jar and b/lib/native/sunos-x86-64.jar differ
diff --git a/lib/native/sunos-x86.jar b/lib/native/sunos-x86.jar
index 761f7fa3e1..80e811f3e5 100755
Binary files a/lib/native/sunos-x86.jar and b/lib/native/sunos-x86.jar differ
diff --git a/lib/native/win32-x86-64.jar b/lib/native/win32-x86-64.jar
index 04acb3ada5..626cd95e9c 100755
Binary files a/lib/native/win32-x86-64.jar and b/lib/native/win32-x86-64.jar differ
diff --git a/lib/native/win32-x86.jar b/lib/native/win32-x86.jar
index c9b508f6bd..c00f625eb4 100644
Binary files a/lib/native/win32-x86.jar and b/lib/native/win32-x86.jar differ
diff --git a/native/callback.c b/native/callback.c
index 52c6165213..2bbedf00d2 100644
--- a/native/callback.c
+++ b/native/callback.c
@@ -686,6 +686,14 @@ dispatch_callback(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
else {
attach_status = (*jvm)->AttachCurrentThread(jvm, (void *)&env, &args);
}
+ if (attach_status != JNI_OK) {
+ free((void *)args.name);
+ if (args.group) {
+ (*env)->DeleteWeakGlobalRef(env, args.group);
+ }
+ fprintf(stderr, "JNA: Can't attach native thread to VM for callback: %d (check stacksize for callbacks)\n", attach_status);
+ return;
+ }
tls = get_thread_storage(env);
if (tls) {
snprintf(tls->name, sizeof(tls->name), "%s", args.name ? args.name : "");
@@ -694,15 +702,11 @@ dispatch_callback(ffi_cif* cif, void* resp, void** cbargs, void* user_data) {
}
// Dispose of allocated memory
free((void *)args.name);
- if (attach_status != JNI_OK) {
- fprintf(stderr, "JNA: Can't attach native thread to VM for callback: %d\n", attach_status);
- return;
- }
if (args.group) {
(*env)->DeleteWeakGlobalRef(env, args.group);
}
}
-
+
if (!tls) {
fprintf(stderr, "JNA: couldn't obtain thread-local storage\n");
return;
diff --git a/native/testlib.c b/native/testlib.c
index 4c8387f3c1..575cf010ae 100644
--- a/native/testlib.c
+++ b/native/testlib.c
@@ -54,7 +54,7 @@ typedef __int64 int64_t;
#define EXPORT __declspec(dllexport)
#define SLEEP(MS) Sleep(MS)
#define THREAD_T DWORD
-#define THREAD_CREATE(TP, FN, DATA) CreateThread(NULL, 0, FN, DATA, 0, TP)
+#define THREAD_CREATE(TP, FN, DATA, STACKSIZE) CreateThread(NULL, STACKSIZE, FN, DATA, 0, TP)
#define THREAD_EXIT() ExitThread(0)
#define THREAD_FUNC(FN,ARG) DWORD WINAPI FN(LPVOID ARG)
#define THREAD_CURRENT() GetCurrentThreadId()
@@ -69,7 +69,15 @@ typedef __int64 int64_t;
#include
#define SLEEP(MS) usleep(MS*1000)
#define THREAD_T pthread_t
-#define THREAD_CREATE(TP, FN, DATA) pthread_create(TP, NULL, FN, DATA)
+#define THREAD_CREATE(TP, FN, DATA, STACKSIZE) {\
+ pthread_attr_t attr;\
+ pthread_attr_init(&attr);\
+ if (STACKSIZE > 0) {\
+ pthread_attr_setstacksize(&attr, STACKSIZE);\
+ }\
+ pthread_create(TP, &attr, FN, DATA);\
+ pthread_attr_destroy(&attr);\
+}
#define THREAD_EXIT() pthread_exit(NULL)
#define THREAD_FUNC(FN,ARG) void* FN(void *ARG)
#define THREAD_RETURN return NULL
@@ -676,7 +684,7 @@ static THREAD_FUNC(thread_function, arg) {
}
EXPORT void
-callVoidCallbackThreaded(void (*func)(void), int n, int ms, const char* name) {
+callVoidCallbackThreaded(void (*func)(void), int n, int ms, const char* name, int stacksize) {
THREAD_T thread;
thread_data* data = (thread_data*)malloc(sizeof(thread_data));
@@ -684,7 +692,7 @@ callVoidCallbackThreaded(void (*func)(void), int n, int ms, const char* name) {
data->sleep_time = ms;
data->func = func;
snprintf(data->name, sizeof(data->name), "%s", name);
- THREAD_CREATE(&thread, &thread_function, data);
+ THREAD_CREATE(&thread, &thread_function, data, stacksize);
}
EXPORT int
diff --git a/test/com/sun/jna/CallbacksTest.java b/test/com/sun/jna/CallbacksTest.java
index 230f81dfb1..39d7497477 100644
--- a/test/com/sun/jna/CallbacksTest.java
+++ b/test/com/sun/jna/CallbacksTest.java
@@ -127,7 +127,7 @@ interface VoidCallback extends Callback {
void callback();
}
void callVoidCallback(VoidCallback c);
- void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name);
+ void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name, int stacksize);
interface VoidCallbackCustom extends Callback {
void customMethodName();
}
@@ -1215,7 +1215,7 @@ protected void callThreadedCallback(TestLibrary.VoidCallback cb,
if (cti != null) {
Native.setCallbackThreadInitializer(cb, cti);
}
- lib.callVoidCallbackThreaded(cb, repeat, sleepms, getName());
+ lib.callVoidCallbackThreaded(cb, repeat, sleepms, getName(), 0);
long start = System.currentTimeMillis();
while (called[0] < returnAfter) {
@@ -1304,6 +1304,25 @@ public void callback() {
waitFor(t[0]);
}
+ public void testSmallStackCallback() throws Exception {
+ // This test runs the callback in a thread, that is allocated a very
+ // small size. It was observed on linux amd64, that a library allocated
+ // a stack size of 64kB, this prevented the JVM to attach to that
+ // thread. The JNIEnv pointer was not checked and this lead to a
+ // hard crash of the JVM.
+ TestLibrary.VoidCallback cb = new TestLibrary.VoidCallback() {
+ @Override
+ public void callback() {
+ System.out.println("Callback called");
+ }
+ };
+
+ lib.callVoidCallbackThreaded(cb, 1, 0, "Test Callback", 32 * 1024);
+
+ // Give the JVM enough time to run the call back
+ Thread.sleep(1 * 1000);
+ }
+
// Detach preference is indicated by the initializer. Thread is attached
// as daemon to avoid VM having to wait for it.
public void testCallbackThreadPersistence() throws Exception {
diff --git a/test/com/sun/jna/DirectCallbacksTest.java b/test/com/sun/jna/DirectCallbacksTest.java
index d15e338e15..ec2d277690 100644
--- a/test/com/sun/jna/DirectCallbacksTest.java
+++ b/test/com/sun/jna/DirectCallbacksTest.java
@@ -73,7 +73,7 @@ public static class DirectTestLibrary implements TestLibrary {
@Override
public native void callVoidCallback(VoidCallback c);
@Override
- public native void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name);
+ public native void callVoidCallbackThreaded(VoidCallback c, int count, int ms, String name, int stacksize);
@Override
public native int callInt32Callback(CustomCallback cb, int arg1, int arg2);