HDFS-11851. getGlobalJNIEnv() may deadlock if exception is thrown. Contributed by Sailesh Mukil.

This commit is contained in:
John Zhuge 2017-06-08 14:15:09 -07:00
parent a062374c39
commit 164c222c4a
2 changed files with 34 additions and 1 deletions

View File

@ -17,8 +17,11 @@
*/ */
#include "expect.h" #include "expect.h"
#include "exception.h"
#include "hdfs/hdfs.h" #include "hdfs/hdfs.h"
#include "jni_helper.h"
#include "native_mini_dfs.h" #include "native_mini_dfs.h"
#include "os/mutexes.h"
#include "os/thread.h" #include "os/thread.h"
#include <errno.h> #include <errno.h>
@ -329,6 +332,23 @@ static int checkFailures(struct tlhThreadInfo *ti, int tlhNumThreads)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
int testRecursiveJvmMutex() {
jthrowable jthr;
JNIEnv *env = getJNIEnv();
if (!env) {
fprintf(stderr, "testRecursiveJvmMutex: getJNIEnv failed\n");
return -EIO;
}
jthr = newRuntimeError(env, "Dummy error to print for testing");
/* printExceptionAndFree() takes the jvmMutex within */
mutexLock(&jvmMutex);
printExceptionAndFree(env, jthr, PRINT_EXC_ALL, "testRecursiveJvmMutex");
mutexUnlock(&jvmMutex);
return 0;
}
/** /**
* Test that we can write a file with libhdfs and then read it back * Test that we can write a file with libhdfs and then read it back
*/ */
@ -341,6 +361,12 @@ int main(void)
1, /* doFormat */ 1, /* doFormat */
}; };
/* Check that the recursive mutex works as expected */
if (testRecursiveJvmMutex() < 0) {
fprintf(stderr, "testRecursiveJvmMutex failed\n");
return EXIT_FAILURE;
}
tlhNumThreadsStr = getenv("TLH_NUM_THREADS"); tlhNumThreadsStr = getenv("TLH_NUM_THREADS");
if (!tlhNumThreadsStr) { if (!tlhNumThreadsStr) {
tlhNumThreadsStr = "3"; tlhNumThreadsStr = "3";

View File

@ -22,7 +22,14 @@
#include <stdio.h> #include <stdio.h>
mutex hdfsHashMutex = PTHREAD_MUTEX_INITIALIZER; mutex hdfsHashMutex = PTHREAD_MUTEX_INITIALIZER;
mutex jvmMutex = PTHREAD_MUTEX_INITIALIZER; mutex jvmMutex;
pthread_mutexattr_t jvmMutexAttr;
__attribute__((constructor)) static void init() {
pthread_mutexattr_init(&jvmMutexAttr);
pthread_mutexattr_settype(&jvmMutexAttr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&jvmMutex, &jvmMutexAttr);
}
int mutexLock(mutex *m) { int mutexLock(mutex *m) {
int ret = pthread_mutex_lock(m); int ret = pthread_mutex_lock(m);