4

Im developing a Spring Boot Web Application, using SWI-Prolog's JPL interface to call Prolog from Java. In development mode everything runs OK. When I deploy it to Docker the first call on JPL through API, runs fine. When I try to call JPL again, JVM crashes.

I use LD_PRELOAD to point to libswipl.so

SWI_HOME_DIR is set also.

LD_LIBRARY_PATH is set to point to libjvm.so

My Controller function:

@PostMapping("/rules/testAPI/")
@Timed
public List<String> insertRule() {
    String use_module_http = "use_module(library(http/http_open)).";
    JPL.init();
    
    Query q1 = new Query(use_module_http);
    if (!q1.hasNext()) {
        System.out.println("Failed to load HTTP Module");
    } else {
        System.out.println("Succeeded to load HTTP Module");
    }

    return null;
}

Console output

1st Call

Succeeded to load HTTP Module

2nd Call

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f31705294b2, pid=16, tid=0x00007f30d2eee700
#
# JRE version: OpenJDK Runtime Environment (8.0_191-b12) (build 1.8.0_191-8u191-b12-2ubuntu0.18.04.1-b12)
# Java VM: OpenJDK 64-Bit Server VM (25.191-b12 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libswipl.so+0xb34b2]  PL_thread_attach_engine+0xe2
#
# Core dump written. Default location: //core or core.16
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

I uploaded the error log file in pastebin. click here

Has anyone faced the same problem? Is there a solution about this?

Note that, I also checked it also with oracle-java-8 but the same error occurs.

UPDATE:

@CapelliC answer didn't work.

Community
  • 1
  • 1
Antifa
  • 377
  • 1
  • 4
  • 14

4 Answers4

1

I think I would try to 'consume' the term. For instance

Query q1 = new Query(use_module_http);
if (!q1.hasNext()) {
    System.out.println("Failed to load HTTP Module");
} else {
    System.out.println("Succeeded to load HTTP Module:"+q1.next().toString());
    // remember q1.close() if there could be multiple soultions
}

or better

if ((new Query(use_module_http)).oneSolution() == null) ...

or still better

if ((new Query(use_module_http)).hasSolution() == false) ...
CapelliC
  • 59,646
  • 5
  • 47
  • 90
1

Not a direct answer because it suggests a different approach, but for a long time I was running a setup where a C++ program I wrote would wrap SWI-Prolog the way you're doing with Spring Boot and it was very difficult to add features to/maintain. About a year ago I went to a totally different approach where I added a MQTT plugin to SWI-Prolog so my Prolog code could run continuously and respond to and send MQTT messages. So now Prolog can interoperate with other modules in a variety of languages (mostly Java), but everything runs in its own process. This has worked out MUCH better for me and I've got everything running in Docker containers - including the MQTT broker. I'm not firmly suggesting MQTT (though I like it), just to consider the approach of having Java and Prolog less tightly coupled.

Steve Prior
  • 322
  • 2
  • 14
  • so you propose to make a container only for Prolog to live in? And what about communication between them? – Antifa Feb 06 '19 at 18:44
  • An HTTP server could be easier, both to develop and evolve, maybe... also given the recent improvements in HTTP routing. – CapelliC Feb 06 '19 at 18:53
  • In my case I have a container running the Mosquitto MQTT broker. A container running Prolog with the MQTT library installed, and numerous other containers and physical devices that publish and/or subscribe to MQTT messages. So the Prolog and other containers don't directly see or communicate with each other, they are pushing messages through the broker. – Steve Prior Feb 06 '19 at 22:06
  • As part of doing this I also switched to a non-blocking message model - for example Prolog receives an event notification so then it sends off a message requesting an image, but does not block waiting for it. The image then comes back as another message which Prolog subscribes to. The key is nothing blocks while waiting for something to happen. The code therefore doesn't have to be multi threaded which makes life MUCH more simple. – Steve Prior Feb 06 '19 at 22:09
  • 1
    My fork of the MQTT library for SWI-Prolog is at: https://github.com/sprior/swi-mqtt-pack – Steve Prior Feb 06 '19 at 22:13
0

Most likely the reason why it is failing the second time is because you are calling JPL.init() again. It should be called only once.

guest
  • 1
0

Finally it was a bug of JPL package. After contacting SWI-Prolog developers, they patched a fix to the SWI-Prolog Git and now the error is gone!

Right configuration, so that Docker container be able to understand JPL is found in this link: Github : env.sh

Antifa
  • 377
  • 1
  • 4
  • 14