Skip to content

Commit b99bd3e

Browse files
committed
HDFS-16084. Fix getJNIEnv crash due to incorrect state set to tls var
Signed-off-by: Kevin Cai <[email protected]>
1 parent b189ef8 commit b99bd3e

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/jni_helper.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -818,26 +818,31 @@ JNIEnv* getJNIEnv(void)
818818
fprintf(stderr, "getJNIEnv: Unable to create ThreadLocalState\n");
819819
return NULL;
820820
}
821-
if (threadLocalStorageSet(state)) {
822-
mutexUnlock(&jvmMutex);
823-
goto fail;
824-
}
825-
THREAD_LOCAL_STORAGE_SET_QUICK(state);
826821

827822
state->env = getGlobalJNIEnv();
828-
mutexUnlock(&jvmMutex);
829-
830823
if (!state->env) {
824+
mutexUnlock(&jvmMutex);
831825
goto fail;
832826
}
833827

834828
jthrowable jthr = NULL;
835829
jthr = initCachedClasses(state->env);
836830
if (jthr) {
831+
mutexUnlock(&jvmMutex);
837832
printExceptionAndFree(state->env, jthr, PRINT_EXC_ALL,
838833
"initCachedClasses failed");
839834
goto fail;
840835
}
836+
837+
if (threadLocalStorageSet(state)) {
838+
mutexUnlock(&jvmMutex);
839+
goto fail;
840+
}
841+
842+
// set the TLS var only when the state passes all the checks
843+
THREAD_LOCAL_STORAGE_SET_QUICK(state);
844+
mutexUnlock(&jvmMutex);
845+
841846
return state->env;
842847

843848
fail:

hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ add_executable(uri_test uri_test.cc)
7474
target_link_libraries(uri_test common gmock_main ${CMAKE_THREAD_LIBS_INIT})
7575
add_memcheck_test(uri uri_test)
7676

77+
add_executable(get_jni_test libhdfs_getjni_test.cc)
78+
target_link_libraries(get_jni_test gmock_main hdfs_static ${CMAKE_THREAD_LIBS_INIT})
79+
add_memcheck_test(get_jni get_jni_test)
80+
7781
add_executable(remote_block_reader_test remote_block_reader_test.cc)
7882
target_link_libraries(remote_block_reader_test test_common reader proto common connection ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} gmock_main ${CMAKE_THREAD_LIBS_INIT})
7983
add_memcheck_test(remote_block_reader remote_block_reader_test)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <gmock/gmock.h>
20+
#include <hdfs/hdfs.h>
21+
#include <jni.h>
22+
23+
// hook the jvm runtime function. expect always failure
24+
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void*) {
25+
return 1;
26+
}
27+
28+
// hook the jvm runtime function. expect always failure
29+
_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM**, void**, void*) {
30+
return 1;
31+
}
32+
33+
TEST(GetJNITest, TestRepeatedGetJNIFailsButNoCrash) {
34+
// connect to nothing, should fail but not crash
35+
EXPECT_EQ(NULL, hdfsConnectNewInstance(NULL, 0));
36+
37+
// try again, should fail but not crash
38+
EXPECT_EQ(NULL, hdfsConnectNewInstance(NULL, 0));
39+
}
40+
41+
int main(int argc, char* argv[]) {
42+
::testing::InitGoogleMock(&argc, argv);
43+
return RUN_ALL_TESTS();
44+
}

0 commit comments

Comments
 (0)