trealla-prolog / trealla

A compact, efficient Prolog interpreter written in plain-old C.
MIT License
268 stars 13 forks source link

GSL: matrix no-size (0x0) segfault #562

Closed flexoron closed 2 months ago

flexoron commented 2 months ago

v2.53.36

$ cat samples/test_matrix_det.mat
#00,0x0,0.0

$

Default behaviour is expected!
$ tpl samples/test_matrix_det.pl
?- main.
gsl: init.c:32: ERROR: permutation length n must be positive integer
Default GSL error handler invoked.
Aborted (core dumped)

GSL error handler switched off!
$ tpl samples/test_matrix_det.pl
?- gsl_set_error_handler_off(_).
   true.
?- main.
Segmentation fault (core dumped)
flexoron commented 2 months ago

Because I don't know how to establish a handler and because GSL must have one, I wrote one just for the sake of formality (to study how gsl errors and tpl might come together)

$ cat gslerr.c

/* GSL error handler */
#include <stdio.h>
#include <signal.h>
#include <gsl/gsl_errno.h>

void *gsl_set_err_hdlr(void *);
void *gsl_reset_err_hdlr(void *v);
static gsl_error_handler_t *old_handler;
void gsl_err_hdlr(const char *r, const char *f, int l, int e) {
  if (1)
    printf ("(caught [%s:%d: %s (%d)])\n", f, l, r, e);
  raise(SIGINT);
}
void *gsl_set_err_hdlr(void *v) {
    old_handler = gsl_set_error_handler(&gsl_err_hdlr);
    return NULL;
}
void *gsl_reset_err_hdlr(void *v) {
    gsl_set_error_handler(old_handler);
    return NULL;
}

$ gcc -fPIC -c gslerr.c
$ gcc -shared -o libgslerr.so gslerr.o -lgsl -lgslcblas -lm
$ cat matrix.pl

:- module(matrix, [main/0]).

:- use_foreign_module('./libgslerr.so', [
       gsl_set_err_hdlr([ptr],ptr),
       gsl_reset_err_hdlr([ptr],ptr)
]).

:- use_module(library(gsl)).

mat_lup_det(M,Size,Det) :-
    gsl_permutation_alloc(Size,P),
    gsl_linalg_LU_decomp(M,P,Signum,_),
    gsl_vector_alloc(Size,B),
    (
        between(1,Size,I),
            I2 is I - 1,
            V is float(I),
            gsl_vector_set(B,I2,V),
            fail; true
    ),
    gsl_vector_alloc(Size,X),
    gsl_linalg_LU_solve(M,P,B,X,_),
    gsl_permutation_free(P),
    gsl_vector_free(B),
    gsl_vector_free(X),
    gsl_linalg_LU_det(M,Signum,Det).

main :-
    open('matrix.mat',read,S),
    mat_read(M,S,Rows,Cols),
    mat_lup_det(M,Rows,Det),
    gsl_matrix_free(M),
    close(S),
    write(Det), nl.
$ cat matrix.mat
#00,0x0,0.0

$ tpl matrix.pl
?- gsl_set_err_hdlr(_,_).
   true.
?- main.

(caught [init.c:32: permutation length n must be positive integer (1)])

Action or (h)elp: g
 [4] gsl_linalg_LU_decomp(265914912,0,_15,_16),gsl_vector_alloc(0,_17),( ... , ... ; true),gsl_vector_alloc(...,...) .
 [1] mat_lup_det(265914912,0,_4)
 [3] main
 [2] mat_read(read,'matrix.mat','<$stream>'(4),'<$stream>'(4))
 [3] open('matrix.mat',read,'<$stream>'(4))
 [2] mat_read(read,'matrix.mat','<$stream>'(4),'<$stream>'(4))
 [3] open('matrix.mat',read,'<$stream>'(4))
  ... .
 false.

?- free_all_memory(allocated(main)). % :-) 

You don't have to worry about such tpl segfaults because gsl handle errors already. So, this way you get both: gsl + tpl tracks and traces.

flexoron commented 2 months ago
gdb check

tpl handler activated!
?- gsl_set_err_hdlr(_,_).
true
: 
#1  0x00007ffff765365e in raise () from /lib64/libc.so.6
#2  0x00007ffff7fb8171 in gsl_err_hdlr () from ./libgslerr.so
#3  0x00007fffe936f867 in gsl_permutation_alloc (n=<optimized out>) at init.c:32 % 
#4  0x00007ffff7e68056 in ffi_call_unix64 () from /lib64/libffi.so.8

gsl_permutation_alloc checks and triggers the handler

**************************

GSL handler switched off!
?- gsl_set_error_handler_off(_).
true
: 
program received signal SIGSEGV, Segmentation fault.
gsl_linalg_LU_decomp (A=0xd08420, p=0x0, signum=0x7fffffff0c30) at lu.c:66

66    if (p->size != M)  //  No Handler, No Check. It crashes here, inside the library

(gdb) bt
#0  gsl_linalg_LU_decomp (A=0xd08420, p=0x0, signum=0x7fffffff0c30) at lu.c:66
#1  0x00007ffff7e68056 in ffi_call_unix64 () from /lib64/libffi.so.8

Looks like it is not tpl's fault.

infradig commented 2 months ago

PS. I have to figure out how to create a handler.

flexoron commented 2 months ago

Yes, tricky. The handler should be able to free gsl _alloc space because of gsl's malloc/free (catchword: memory leaks).