lucene-pylucene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Patrick J. McNerthney (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (PYLUCENE-17) Possible race condition with pylucene attachCurrentThread
Date Tue, 26 Jun 2012 02:00:44 GMT

    [ 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

        

Mime
View raw message