Closed afifatariq closed 3 years ago
Unfortunately your issue does not contain enough information to even speculate as to the source. If you can replicate the issue and isolate it to the critical elements then perhaps I could give a better response. There are lots of possible ways for a dead lock to occur in Java and Python. JPype simply uses JNI to initiate Java calls so there is no waiting beyond whatever Java is performing. There is a global Python lock which must be reacquired upon returning, thus unless Python is stalled there is no deadlock potential there.
Is there any way to check if this lock is the reason? I am using a multi-processor system and the code is too long to be able to reproduce with just the jpype stuff. But I know for sure that the problem is because a java call is made and the python side keeps waiting for a response which it doesn't get so just hangs. It would be great if you could suggest something that I can check in my python program.
About the only way to check the status at this level would be to compile JPype with logging and look a the logger output. I used it for this purpose to debug the multi threaded examples. But barring this I don't have much advice.
I have run the code with trace and I am getting the following traceback (These are the last few lines of the trace only).
Parsing 2 PDDL files supervised.py(153): self.enhsp = enhsp(pddl_files[0]) --- modulename: enhsp_interface, funcname: init enhsp_interface.py(35): if not jpype.isThreadAttachedToJVM(): --- modulename: _core, funcname: func2 _core.py(71): import warnings _core.py(72): if not func2._warned: _core.py(73): warnings.warn(func2._warning % (func2._real.module, func2._real.name), _core.py(74): category=DeprecationWarning, stacklevel=2) _core.py(75): func2._warned = True _core.py(76): return func2._real(*args, *kwargs) --- modulename: _core, funcname: isThreadAttachedToJVM _core.py(361): return _jpype.isThreadAttachedToJVM() enhsp_interface.py(37): domainFile = jpype.JString(domain) --- modulename: _jstring, funcname: new _jstring.py(33): if cls != JString: _jstring.py(35): cls = _jpype.JClass("java.lang.String") --- modulename: _jclass, funcname: new _jclass.py(79): if loader and isinstance(jc, str): _jclass.py(83): if isinstance(jc, str) and jc.endswith(">"): _jclass.py(99): return _jpype._getClass(jc) _jstring.py(36): return cls(args) enhsp_interface.py(38): print("HERE") HERE enhsp_interface.py(39): self.domain = PddlDomain(domainFile);
As you can see after the last line which is a call to the java class PddlDomain, nothing happens. No error or anything.
This is a Python trace. If you want the JNI trace, you must recompile JPype with --enable-tracing
as specified in the devel guide.
Okay so I have just tried it with this. The traceback is the following:
PyJPObject_new JPMethodDispatch::invokeConstructor JPMethodDispatch::findOverload JPMethodDispatch::findOverload: Checking overload
JPMethodDispatch::findOverload: Got overloads to check 2 JPMethodDispatch::findOverload: Trying to match public com.hstairs.ppmajal.domain.PddlDomain(java.util.Collection,com.hstairs.ppmajal.problem.PDDLObjects,java.util.Set,java.util.Collection) JPTypeManager::populateMethod JPTypeManager::populateMethod: Method 0x55bd39829a10 JPTypeFactory_populateMethod < JPTypeFactory_populateMethod < JPTypeManager::populateMethod JPMethod::matches JPMethod::matches: Flags 0 0 0 JPMethod::matches: arguments length 1 JPMethod::matches: types length 4 JPMethod::matches: Argument length mismatch 1 4 < JPMethod::matches JPMethodDispatch::findOverload: match ended 0 JPMethodDispatch::findOverload: Trying to match public com.hstairs.ppmajal.domain.PddlDomain(java.lang.String) JPTypeManager::populateMethod JPTypeManager::populateMethod: Method 0x55bd398cab60 JPTypeFactory_populateMethod < JPTypeFactory_populateMethod < JPTypeManager::populateMethod JPMethod::matches JPMethod::matches: Flags 0 0 0 JPMethod::matches: arguments length 1 JPMethod::matches: types length 1 JPMethod::matches: Match args JPStringType::findJavaConversion JPConversionNull::matches < JPConversionNull::matches JPConversionObject::matches < JPConversionObject::matches < JPStringType::findJavaConversion JPMethod::matches: Result 3 < JPMethod::matches JPMethodDispatch::findOverload: match ended 3 < JPMethodDispatch::findOverload JPMethod::invokeConstructor JPMethod::packArgs JPMethod::packArgs: skip 0 JPMethod::packArgs: offset 0 JPMethod::packArgs: arguments length 1 JPMethod::packArgs: types length 1 JPMethod::packArgs: Pack fixed total= 1 < JPMethod::packArgs
And then nothing else is displayed.
Hi, just wondering if you looked into this
Not much to look at. Everything in the log is normal operations. If you add a flush command to the logger you would see that the next command would be to release the lock and call java. I would recommend checking to see if the global lock has a log statement and enable that to see if it gives additional clues.
Only by comparing the logs where something works and where it fails is it likely to point to a problem. If this was an error that could be replicated using some trivial code I could see if I can identify it, but unfortunately there is little I can do at present.
Okay. Just one more thing. If I have an error trace that stops at JPClass:: invoke and doesn't do the next step which should be JPMethodDispatch:: invoke, then what could be the problem?
Here is the trace for that:
PyJPMethod_call PyJPMethod_call: hasNext JPMethodDispatch::invoke JPMethodDispatch::findOverload JPMethodDispatch::findOverload: Checking overload hasNext JPMethodDispatch::findOverload: Got overloads to check 1 JPMethodDispatch::findOverload: Trying to match public abstract boolean java.util.Iterator.hasNext() JPMethod::matches JPMethod::matches: Flags 0 1 1 JPMethod::matches: arguments length 1 JPMethod::matches: types length 1 JPMethod::matches: Take this JPMethod::matches: Match args JPClass::findJavaConversion JPConversionNull::matches < JPConversionNull::matches JPConversionObject::matches JPConversionObject::matches: assignable 1 java.util.LinkedHashMap.LinkedKeyIterator java.util.Iterator < JPConversionObject::matches < JPClass::findJavaConversion JPMethod::matches: Result 2 < JPMethod::matches JPMethodDispatch::findOverload: match ended 2 JPMethodDispatch::findOverload: Best match public abstract boolean java.util.Iterator.hasNext() < JPMethodDispatch::findOverload JPMethod::invoke JPMethod::packArgs JPMethod::packArgs: skip 1 JPMethod::packArgs: offset 0 JPMethod::packArgs: arguments length 1 JPMethod::packArgs: types length 1 JPMethod::packArgs: Pack fixed total= 1 < JPMethod::packArgs JPMethod::invoke: invoke virtual public abstract boolean java.util.Iterator.hasNext() < JPMethod::invoke < JPMethodDispatch::invoke < PyJPMethod_call PyJPMethod_dealloc < PyJPMethod_dealloc PyJPObject_getattro PyJPMethod_get PyJPMethod_create < PyJPMethod_create < PyJPMethod_get < PyJPObject_getattro PyJPMethod_call PyJPMethod_call: next JPMethodDispatch::invoke JPMethodDispatch::findOverload JPMethodDispatch::findOverload: Checking overload next JPMethodDispatch::findOverload: Got overloads to check 1 JPMethod::matches JPMethod::matches: Flags 0 1 1 JPMethod::matches: arguments length 1 JPMethod::matches: types length 1 JPMethod::matches: Take this JPMethod::matches: Match args JPClass::findJavaConversion JPConversionNull::matches < JPConversionNull::matches JPConversionObject::matches < JPConversionObject::matches < JPClass::findJavaConversion JPMethod::matches: Result 3 < JPMethod::matches < JPMethodDispatch::findOverload JPMethod::invoke JPMethod::packArgs JPMethod::packArgs: skip 1 JPMethod::packArgs: offset 0 JPMethod::packArgs: arguments length 1 JPMethod::packArgs: types length 1 JPMethod::packArgs: Pack fixed total= 1 < JPMethod::packArgs JPMethod::invoke: invoke virtual public final java.lang.Object java.util.LinkedHashMap$LinkedKeyIterator.next() JPClass::invoke JPTypeManager::findClassForObject JPTypeManager::findClassForObject: ClassName com.hstairs.ppmajal.conditions.Predicate < JPTypeManager::findClassForObject JPClass::convertToPythonObject JPTypeManager::findClassForObject JPTypeManager::findClassForObject: ClassName com.hstairs.ppmajal.conditions.Predicate < JPTypeManager::findClassForObject PyJPClass_create id="0x558c1a562930" < PyJPClass_create PyJPValue_alloc PyJPValue_alloc: alloc com.hstairs.ppmajal.conditions.Predicate 0x7efcceddf870 < PyJPValue_alloc < JPClass::convertToPythonObject < JPClass::invoke < JPMethod::invoke
I would recommend adding more instrumentation to that spot to see if you can see what JNI call is being made.
I am extensively using jpype in my program and this problem has occurred on multiple occasions at different code blocks. Sometimes it would run fine and give an output instantaneously. But sometimes it doesn't get a response from the java side and the python side just keeps waiting for it.