I have been experimenting with the multithreading features of JPL. As far as I understand from the comments in the source code one different Prolog engine is assigned per Java thread. Apparently there is a problem when a query is started in thread A, another query is executed in thread B (spawned by thread A), and a third query is executed again in thread A.
The following snippet of code illustrates the problem:
public static void main(String[] args) {
try {
...
Query query;
query = new Query("true");
System.out.println(query.hasSolution()); //succeeds
Thread t = new Thread() {
@Override
public void run() {
Query query2 = new Query("true");
System.out.println(query2.hasSolution()); //succeeds
}
};
t.start();
t.join();
query = new Query("true");
System.out.println(query.hasSolution()); //fatal error
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Since the JPL documentation mentions that no two queries can be active at the same time, the code waits until completion of the thread before continuing to the last query (it is not yet clear to me if that constraint applies only to queries in the same thread or if it applies to queries in different threads and engines).
In the previous example, only the first two queries succeed. When the third query is executed I obtain this fatal error:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x000000010db65bd5, pid=79191, tid=7171
#
# JRE version: 7.0_06-b24
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.2-b09 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C [libYap.dylib+0x125bd5] PL_open_foreign_frame+0x45
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
...
Is this a bug in JPL ? in that case does someone know a workaround for using JPL with multithreading ?
I have tested with both YAP version 6.2.2 and 6.3.2 with the same results.
UPDATE:
As @sharky suggested, apparently it is a problem with the YAP binaries (or the JPL port for YAP). When using SWI the example showed in the question is working fine.
Still I am puzzled with the JPL behavior in multi-threaded programs.
Taken a look to the source code and comments of the open
method in the Query
class from the JPL library:
public synchronized final void open() {
...
if (Prolog.thread_self() == -1) { // this Java thread has no attached Prolog engine?
engine = Prolog.attach_pool_engine(); // may block for a while, or fail
} else { // this Java thread has an attached engine
engine = Prolog.current_engine();
}
...
}
it seems to say that JPL will create a new logic engine per thread. However, if I execute this simple program:
Thread t = new Thread() {
@Override
public void run() {
Query query = new Query("assert(x)");
query.hasSolution()
query = new Query("x");
System.out.println("Thread1 x:" + query.hasSolution()); //query succeeds
}
};
t.start();
t.join();
t = new Thread() {
@Override
public void run() {
Query query = new Query("x");
System.out.println("Thread2 x:" + query.hasSolution()); //query also succeeds
}
};
t.start();
t.join();
I can see the following output:
Thread1 x:true
Thread2 x:true
So apparently the second thread is accessing the same Prolog engine than the first one, not a new one as the source code and its comments seems to suggest.
If someone has experience with JPL and multithreading please clarify this.