[ https://issues.apache.org/jira/browse/PYLUCENE-17?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13401106#comment-13401106 ]
Patrick J. McNerthney commented on PYLUCENE-17: ----------------------------------------------- (I was in the middle of composing this comment when your comment showed up. I haven't had a chance to look at it, but once this comment has been submitted.) "And with your initializing$ change, you make getClass(true) return NULL so that the locked path is taken." - Actually...not quite right. Here is the code generated for Boolean::initializeClass: jclass Boolean::initializeClass(bool getOnly) { if (getOnly) return (jclass) (class$ == NULL ? NULL : class$->this$); if (!class$) { if (initializing$) return NULL; initializing$ = true; jclass cls = (jclass) env->findClass("java/lang/Boolean"); mids$ = new jmethodID[max_mid]; mids$[mid_init$_bb0c767f] = env->getMethodID(cls, "<init>", "(Z)V"); mids$[mid_init$_5fdc3f48] = env->getMethodID(cls, "<init>", "(Ljava/lang/String;)V"); mids$[mid_booleanValue_54c6a16a] = env->getMethodID(cls, "booleanValue", "()Z"); mids$[mid_compareTo_d07f0c91] = env->getMethodID(cls, "compareTo", "(Ljava/lang/Boolean;)I"); mids$[mid_compareTo_290588f1] = env->getMethodID(cls, "compareTo", "(Ljava/lang/Object;)I"); mids$[mid_equals_290588e2] = env->getMethodID(cls, "equals", "(Ljava/lang/Object;)Z"); mids$[mid_getBoolean_5fdc3f44] = env->getStaticMethodID(cls, "getBoolean", "(Ljava/lang/String;)Z"); mids$[mid_hashCode_54c6a179] = env->getMethodID(cls, "hashCode", "()I"); mids$[mid_parseBoolean_5fdc3f44] = env->getStaticMethodID(cls, "parseBoolean", "(Ljava/lang/String;)Z"); mids$[mid_toString_14c7b5c5] = env->getMethodID(cls, "toString", "()Ljava/lang/String;"); mids$[mid_toString_445a175e] = env->getStaticMethodID(cls, "toString", "(Z)Ljava/lang/String;"); mids$[mid_valueOf_a98d5bba] = env->getStaticMethodID(cls, "valueOf", "(Z)Ljava/lang/Boolean;"); mids$[mid_valueOf_9d4a8ff9] = env->getStaticMethodID(cls, "valueOf", "(Ljava/lang/String;)Ljava/lang/Boolean;"); FALSE = new Boolean(env->getStaticObjectField(cls, "FALSE", "Ljava/lang/Boolean;")); TRUE = new Boolean(env->getStaticObjectField(cls, "TRUE", "Ljava/lang/Boolean;")); TYPE = new ::java::lang::Class(env->getStaticObjectField(cls, "TYPE", "Ljava/lang/Class;")); initializing$ = false; class$ = (::java::lang::Class *) new JObject(cls); } return (jclass) class$->this$; } This part: if (getOnly) return (jclass) (class$ == NULL ? NULL : class$->this$); always handles all cases of being called without the mutex lock in place and works exactly like your version does. Remember, all the rest of the code will be executing under the mutex lock, so it is not an accurate statement to say that "you make getClass(true) return NULL so that the locked path is taken.". Following along in the rest of the code, this part: if (!class$) { also works exactly the same as before. If another thread managed to initialize this class before we got the mutex, then no need for us to initialize it. Next is this new code: if (initializing$) return NULL; This first checks to see if this class is currently being initialized. Since there is only one intializeClass mutex, there can only be one thread at a time performing initialization and since the current thread has the mutex, the current thread is the only one who could be recursively initializing this class. So, if we are in the middle of initializing this class, just return null, because the return value is not needed. If we did not return now, we would end up in an infinite loop. initializing$ = true; This flags this class as being actively initialized. Then, further down in the code are these two statements: FALSE = new Boolean(env->getStaticObjectField(cls, "FALSE", "Ljava/lang/Boolean;")); TRUE = new Boolean(env->getStaticObjectField(cls, "TRUE", "Ljava/lang/Boolean;")); This is was is doing to cause the recursive call back into the initializeClass method. The Boolean constructor does the call to "env->getClass(initializeClass)", but the return value is ignored. This is why it is okay for the above returning of NULL if initializing$ is true. This code: initializing$ = false; class$ = (::java::lang::Class *) new JObject(cls); Flags this class as no longer being actively initialized and then sets the class$ field. Note that this is occurring after the above initialization of FALSE and TRUE now. > Possible race condition with pylucene attachCurrentThread > --------------------------------------------------------- > > Key: PYLUCENE-17 > URL: https://issues.apache.org/jira/browse/PYLUCENE-17 > Project: PyLucene > Issue Type: Bug > Environment: Linux 2.6.39 > Sun jdk 1.6.26 > Reporter: Greg Bowyer > Labels: pylucene > Attachments: PYLUCENE-17-3.patch, PYLUCENE-17-4.patch, backtrace, > diff.17.txt, lucene-threadtest.py > > > It looks like there is a possible race that can cause null pointer exceptions > in the JVM, making it crash > Because its a race it is hard to reproduce, the best luck I have had so far > is dropping my FS cache in the OS, which seems to slow down the > initialisation of the JVM enough to make it easier to reproduce. > Attached is my test case > Test session follows > --------------------------------------------------------------- > greg@localhost ~/programming/python $ sudo bash -c 'echo 3 > > /proc/sys/vm/drop_caches' > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > # > # A fatal error has been detected by the Java Runtime Environment: > # > # SIGSEGV (0xb) at pc=0x00007f79226b35c8, pid=26581, tid=140158003312384 > # > # JRE version: 6.0_26-b03 > # Java VM: Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode linux-amd64 > compressed oops) > # Problematic frame: > # V [libjvm.so+0x4b05c8] instanceKlass::cached_itable_index(unsigned > long)+0x18 > # > # An error report file with more information is saved as: > # /home/greg/programming/python/hs_err_pid26581.log > # > # If you would like to submit a bug report, please visit: > # http://java.sun.com/webapps/bugreport/crash.jsp > # > Aborted (core dumped) > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > greg@localhost ~/programming/python $ rm -r /tmp/test-index/ > greg@localhost ~/programming/python $ sudo bash -c 'echo 3 > > /proc/sys/vm/drop_caches' > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > # > # A fatal error has been detected by the Java Runtime Environment: > [thread 139988165344768 also had an error][thread 139988165344768 also had an > error]# > # SIGSEGV (0xb) > at pc=0x00007f5197550a29, pid=27657, tid=139988039468800 > # > # JRE version: 6.0_26-b03 > # Java VM: Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode linux-amd64 > compressed oops) > # Problematic frame: > # V [libjvm.so+0x4f2a29] unsigned+0x299 > # > # An error report file with more information is saved as: > # /home/greg/programming/python/hs_err_pid27657.log > # > # If you would like to submit a bug report, please visit: > # http://java.sun.com/webapps/bugreport/crash.jsp > # > Aborted (core dumped) > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > greg@localhost ~/programming/python $ sudo bash -c 'echo 3 > > /proc/sys/vm/drop_caches' > greg@localhost ~/programming/python $ python ./lucene-threadtest.py > # > # A fatal error has been detected by the Java Runtime Environment: > # > # SIGSEGV (0xb) at pc=0x00007f51bc2eaa1e, pid=28124, tid=139988377052928 > # > # JRE version: 6.0_26-b03 > # Java VM: Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode linux-amd64 > compressed oops) > # Problematic frame: > # V [libjvm.so+0x4f2a1e] unsigned+0x28e > # > # An error report file with more information is saved as: > # /home/greg/programming/python/hs_err_pid28124.log > # > # If you would like to submit a bug report, please visit: > # http://java.sun.com/webapps/bugreport/crash.jsp > # > Aborted (core dumped) > greg@localhost ~/programming/python $ -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa For more information on JIRA, see: http://www.atlassian.com/software/jira