Closed flexoron closed 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.
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.
PS. I have to figure out how to create a handler.
Yes, tricky. The handler should be able to free gsl _alloc space because of gsl's malloc/free (catchword: memory leaks).
v2.53.36