3
votes

Conteneur Docker avec SWI-Prolog terminé avec une erreur fatale

Je développe une application Web Spring Boot, en utilisant l'interface JPL de SWI-Prolog pour appeler Prolog depuis Java. En mode développement, tout fonctionne correctement. Lorsque je le déploie sur Docker, le premier appel sur JPL via l'API fonctionne correctement. Lorsque j'essaye d'appeler à nouveau JPL, la JVM plante.

J'utilise LD_PRELOAD pour pointer vers libswipl.so[

SWI_HOME_DIR strong> est également défini.

LD_LIBRARY_PATH est défini pour pointer vers libjvm.so

Fonction de mon contrôleur:

#
# 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.
#

Sortie de la console

1er appel

Succeeded to load HTTP Module

2ème appel

@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;
}

J'ai téléchargé le fichier journal des erreurs dans pastebin. cliquez ici

Quelqu'un at-il été confronté au même problème? Y a-t-il une solution à ce problème?

Notez que je l'ai également vérifié avec oracle-java-8 mais la même erreur se produit.

MISE À JOUR:

La réponse @CapelliC n'a pas fonctionné.


0 commentaires

4 Réponses :


1
votes

Je pense que j'essaierais de «consommer» le terme. Par exemple

if ((new Query(use_module_http)).hasSolution() == false) ...

ou mieux

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

ou encore mieux

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
}


8 commentaires

je vais essayer et je publierai les résultats.


mais pourquoi il s'exécute la première fois et la seconde plante ??


Pardon, je n'ai pas essayé jusqu'à présent ... Je comprends que cela n'a pas aidé?


Oui, cela n'a pas aidé. J'ai essayé les trois alternatives que vous avez publiées, mais toujours la même sortie


Avez-vous essayé le premier indice avec q1.close () sans commentaire? Mais admettez que ce serait étrange si cela fonctionnait ...


Encore le même. Avez-vous en tête une autre solution ??


pas vraiment, désolé ... peut-être que j'essaierais avec try / catch du côté Java, ou un bon débogueur, d'inspecter le cadre. Connaissez-vous les trames étrangères dans l'interface étrangère SWI-Prolog?


existe-t-il un moyen de déboguer un fichier de guerre dans le conteneur docker? je ne comprends pas la dernière partie de votre commentaire ...



1
votes

Ce n'est pas une réponse directe car cela suggère une approche différente, mais pendant longtemps, j'exécutais une configuration dans laquelle un programme C ++ que j'avais écrit enveloppait SWI-Prolog comme vous le faites avec Spring Boot et il était très difficile de ajouter des fonctionnalités à / maintenir. Il y a environ un an, j'ai adopté une approche totalement différente où j'ai ajouté un plugin MQTT à SWI-Prolog afin que mon code Prolog puisse fonctionner en continu et répondre et envoyer des messages MQTT. Alors maintenant, Prolog peut interagir avec d'autres modules dans une variété de langages (principalement Java), mais tout fonctionne dans son propre processus. Cela a beaucoup mieux fonctionné pour moi et j'ai tout fonctionné dans des conteneurs Docker - y compris le courtier MQTT. Je ne suggère pas fermement MQTT (bien que j'aime ça), juste pour considérer l'approche consistant à avoir Java et Prolog moins étroitement couplés.


5 commentaires

alors vous proposez de faire un conteneur uniquement pour Prolog? Et qu'en est-il de la communication entre eux?


Un serveur HTTP pourrait être plus facile, à la fois à développer et à faire évoluer, peut-être ... également compte tenu des récentes améliorations du routage HTTP.


Dans mon cas, j'ai un conteneur exécutant le courtier Mosquitto MQTT. Un conteneur exécutant Prolog avec la bibliothèque MQTT installée et de nombreux autres conteneurs et périphériques physiques qui publient et / ou s'abonnent à des messages MQTT. Ainsi, le Prolog et les autres conteneurs ne se voient pas ou ne communiquent pas directement entre eux, ils envoient des messages via le courtier.


Dans ce cadre, j'ai également basculé vers un modèle de message non bloquant - par exemple, Prolog reçoit une notification d'événement, alors il envoie un message demandant une image, mais ne bloque pas l'attente. L'image revient alors comme un autre message auquel Prolog souscrit. La clé est que rien ne bloque en attendant que quelque chose se passe. Le code n'a donc pas besoin d'être multi thread, ce qui rend la vie BEAUCOUP plus simple.


Mon fork de la bibliothèque MQTT pour SWI-Prolog est à: github.com/sprior/swi-mqtt -pack



0
votes

La raison la plus probable pour laquelle il échoue la deuxième fois est que vous appelez à nouveau JPL.init () . Il ne doit être appelé qu'une seule fois.


0 commentaires

0
votes

Enfin, c'était un bogue du package JPL. Après avoir contacté les développeurs SWI-Prolog, ils ont corrigé un correctif sur SWI-Prolog Git et maintenant l'erreur a disparu!

La bonne configuration, pour que le conteneur Docker puisse comprendre JPL se trouve dans ce lien: Github: env.sh


0 commentaires