yuce / pyswip

PySwip is a Python - SWI-Prolog bridge enabling to query SWI-Prolog in your Python programs. It features an (incomplete) SWI-Prolog foreign language interface, a utility class that makes it easy querying with Prolog and also a Pythonic interface.
MIT License
464 stars 97 forks source link

Core dump #143

Open damianoazzolini opened 2 years ago

damianoazzolini commented 2 years ago

Hi, I'm trying to use this package with SWI-Prolog version 8.5.8. However, I get a core dump for every program I test. For example, with the example program in the coin folder I get:

(p3.7) damiano[OLD]@192.168.1.5:.../Ricerca/Test$ p3 pl_interface.py 
[Thread 1 (main) at Sat Mar 12 16:44:19 2022] /mnt/c/Users/damia/Desktop/Mio/swipl-devel/src/pl-fli.c:2556: PL_put_chars: Assertion failed: 0
C-stack trace labeled "assert_fail":
  [0] save_backtrace() at /mnt/c/Users/damia/Desktop/Mio/swipl-devel/src/os/pl-cstack.c:333 [0x7f82eb365be7]
  [1] __assert_fail() at /mnt/c/Users/damia/Desktop/Mio/swipl-devel/src/pl-assert.c:103 [0x7f82eb308d37]
  [2] PL_put_chars() at /mnt/c/Users/damia/Desktop/Mio/swipl-devel/src/pl-fli.c:2556 [0x7f82eb3387e1]
  [3] ffi_call_unix64() at :? [0x7f82ece5a9dd]
  [4] ffi_call_int() at ffi64.c:? [0x7f82ece5a067]
  [5] _call_function_pointer() at /usr/local/src/conda/python-3.7.11/Modules/_ctypes/callproc.c:837 [0x7f82ebbdc3a7]
  [6] PyCFuncPtr_call() at /usr/local/src/conda/python-3.7.11/Modules/_ctypes/_ctypes.c:4036 [0x7f82ebbdce14]
  [7] python3(_PyObject_FastCallKeywords+0x15c) [0x7f82ed01b88c]
  [8] python3(_PyEval_EvalFrameDefault+0x47e5) [0x7f82ed063545]
  [9] python3(+0x191375) [0x7f82ed02d375]
  [10] python3(_PyMethodDef_RawFastCallKeywords+0xe9) [0x7f82ecfe5959]
  [11] python3(_PyEval_EvalFrameDefault+0x44f8) [0x7f82ed063258]
  [12] python3(_PyEval_EvalCodeWithName+0x273) [0x7f82ecfb4bb3]
  [13] python3(_PyFunction_FastCallKeywords+0x631) [0x7f82ecfd51c1]
  [14] python3(+0x1800c5) [0x7f82ed01c0c5]
  [15] python3(_PyEval_EvalFrameDefault+0x48a2) [0x7f82ed063602]
  [16] python3(_PyFunction_FastCallKeywords+0x187) [0x7f82ecfd4d17]
  [17] python3(_PyEval_EvalFrameDefault+0x3f5) [0x7f82ed05f155]
  [18] python3(_PyEval_EvalCodeWithName+0x273) [0x7f82ecfb4bb3]
  [19] python3(PyEval_EvalCode+0x23) [0x7f82ecfb5ee3]
  [20] python3(+0x227802) [0x7f82ed0c3802]
  [21] python3(PyRun_FileExFlags+0x9e) [0x7f82ed0cd94e]
  [22] python3(PyRun_SimpleFileExFlags+0x1bb) [0x7f82ed0cdb3b]
  [23] python3(+0x232c3a) [0x7f82ed0cec3a]
  [24] python3(_Py_UnixMain+0x3c) [0x7f82ed0ceccc]
  [25] __libc_start_main() at /build/glibc-S7Ft5T/glibc-2.23/csu/../csu/libc-start.c:325 [0x7f82ebf00840]
  [26] python3(+0x1d7555) [0x7f82ed073555]
Annullato (core dump creato)

Any idea how to fix this?

andreasknoben commented 2 years ago

I got the same error with pyswip version 0.2.10. Installing pyswip 0.2.9 (using pip install pyswip==0.2.9) solved the issue for me.

andreasknoben commented 2 years ago

Update: I got a different error using pyswip 0.2.9. However, I found out that you can use pyswip 0.2.10 in conjunction with swipl version 8.4.2 (so not the development release from git, but the stable release from the tar.gz files on their website). You can find it here (under sources).

kamahen commented 2 years ago

I get a similar error.

$ uname -a
Linux penguin 5.10.110-15808-ge5740beba59b #1 SMP PREEMPT Tue May 24 10:50:29 PDT 2022 x86_64 GNU/Linux
$ swipl --version
SWI-Prolog version 8.5.12 for x86_64-linux
$ python3.9 -mpip install pyswip --user
Collecting pyswip
  Downloading pyswip-0.2.10-py2.py3-none-any.whl (27 kB)
Installing collected packages: pyswip
Successfully installed pyswip-0.2.10
$ python3.9
Python 3.9.2 (default, Feb 28 2021, 17:03:44) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyswip import Prolog
>>> prolog=Prolog()
>>> prolog.assertz("father(michael, john)")
[Thread 1 (main) at Tue Jun 21 09:44:35 2022] ../src/pl-fli.c:2556: PL_put_chars: Assertion failed: 0
C-stack trace labeled "assert_fail":
  [0] save_backtrace() at /home/peter/src/swipl-devel/build/../src/os/pl-cstack.c:334 [0x7bc9b158166e]
  [1] __assert_fail() at /home/peter/src/swipl-devel/build/../src/pl-assert.c:103 [0x7bc9b1524176]
  [2] PL_put_chars() at /home/peter/src/swipl-devel/build/../src/pl-fli.c:2556 (discriminator 1) [0x7bc9b1552b24]
  [3] ffi_prep_go_closure() at ??:? [0x7bc9b16d3d1d]
  [4] ffi_closure_free() at ??:? [0x7bc9b16d3289]
  [5] ??() at ??:0 [0x7bc9b1992360]
  [6] ??() at ??:0 [0x7bc9b1991e05]
  [7] python3.9(_PyObject_MakeTpCall+0x39b) [0x51d89b]
  [8] python3.9(_PyEval_EvalFrameDefault+0x5654) [0x5170e4]
  [9] python3.9(+0x14c00a) [0x54c00a]
  [10] python3.9(+0x1c7290) [0x5c7290]
  [11] python3.9(+0x1298c4) [0x5298c4]
  [12] python3.9(_PyEval_EvalFrameDefault+0x525) [0x511fb5]
  [13] python3.9(+0x1106ed) [0x5106ed]
  [14] python3.9(_PyFunction_Vectorcall+0x361) [0x528d21]
  [15] python3.9(+0x13bcfb) [0x53bcfb]
  [16] python3.9(_PyEval_EvalFrameDefault+0x53e6) [0x516e76]
  [17] python3.9(+0x1106ed) [0x5106ed]
  [18] python3.9(_PyEval_EvalCodeWithName+0x47) [0x510497]
  [19] python3.9(PyEval_EvalCode+0x23) [0x5f5be3]
  [20] python3.9(+0x219de7) [0x619de7]
  [21] python3.9(+0x215610) [0x615610]
  [22] python3.9(+0x59cb3) [0x459cb3]
  [23] python3.9(PyRun_InteractiveLoopFlags+0xd5) [0x459911]
  [24] python3.9(PyRun_AnyFileExFlags+0x55) [0x6194f5]
  [25] python3.9(+0x4bca9) [0x44bca9]
  [26] python3.9(Py_BytesMain+0x29) [0x5ea6e9]
  [27] __libc_start_main() at ./csu/../csu/libc-start.c:308 [0x7bc9b1df2d0a]
  [28] python3.9(_start+0x2a) [0x5ea5ea]
Aborted (core dumped)
peter@penguin:~/src$ 

The crash occurs at the assert(0) in pl-fli.c:

  if ( flags == PL_ATOM )
    w = textToAtom(&text);
  else if ( flags == PL_STRING )
    w = textToString(&text);
  else if ( flags == PL_CODE_LIST || flags == PL_CHAR_LIST )
  { PL_put_variable(t);
    rc = PL_unify_text(t, 0, &text, flags);
  } else
    assert(0);
andreasknoben commented 2 years ago

@kamahen Does this error still occur if you use swipl version 8.4.3, the current stable release, from this page? That solved the issue for me.

kamahen commented 2 years ago

The example on the github page works fine with swipl 8.4.3. However, 8.4.3 is quite old and most SWI-Prolog users have the development version (8.5.12), which has added quite a few features. I think that 8.4.3 will soon be replaced by 8.5.*.

When I think of it, pyswip does foreign language calls (via ctypes), and the ABI is almost certainly different between swipl 8.4.3 and 8.5.12; and that would account for the crash.

kamahen commented 2 years ago

Perhaps pyswip should check the SWI-Prolog version and throw an exception if it isn't what's expected. https://www.swi-prolog.org/pldoc/doc_for?object=c(%27PL_version_info%27)

andreasknoben commented 11 months ago

If I understand correctly, the defined constants have been copied from SWI-Prolog manually, so whenever they change there they are not changed in pyswip, causing a crash?

aleden commented 11 months ago

If I understand correctly, the defined constants have been copied from SWI-Prolog manually, so whenever they change there they are not changed in pyswip, causing a crash?

Yes. pyswip and swi-prolog each have their own definitions of "TERM-TYPE CONSTANTS" (e.g. PL_VARIABLE, PL_ATOM, PL_INTEGER, etc).

A cursory reading of pyswip/core.py indicates that there are effectively two distinct sets of values for these constants, and the first is chosen if PL_VERSION<80200 (i.e. swi-prolog version < 8.2.0). But how is PL_VERSION determined? In pyswip/core.py we have the following code:

try:                                                                                                                                    
    PL_version = _lib.PL_version                                                                                                        
    ...
except AttributeError:                                                                                                                  
    PL_VERSION=70000  # Best guess. When was PL_version introduced?                                                                     

On my debian bullseye system (swi-prolog-core 8.2.4+dfsg-1), PL_version exists:

$ python3
>>> import ctypes
>>> _lib = ctypes.CDLL("/usr/lib/libswipl.so", mode=ctypes.RTLD_GLOBAL)
>>> print(_lib.PL_version)
<_FuncPtr object at 0x7f0803d347c0>

But on my archlinux system (swi-prolog 9.0.4-2), PL_version does not:

$ python
>>> import ctypes
>>> _lib = ctypes.CDLL("/usr/lib/swipl/lib/x86_64-linux/libswipl.so", mode=ctypes.RTLD_GLOBAL)
>>> print(_lib.PL_version)
...
AttributeError: /usr/lib/swipl/lib/x86_64-linux/libswipl.so: undefined symbol: PL_version

It appears that at some point swip-prolog stopped exporting the symbol PL_version. Consequently, the code in pyswip is going to assume PL_VERSION=70000 (7.0.0 instead of 9.0.4).

This appears to explain why I am seeing the assert(0) from pl-fli.c on my system.

qq765490023 commented 10 months ago

ya!!!! I fixed it by changing the version of pyswip!