Re: Raising Prolog exceptions from C code (2nd attempt)

Joseph Benden wrote:
Hello,
The Prolog exceptions that I am successfully raising from both C and C++ code is based off of the Emit_Syntax_Error call.
Example:
Emit_Syntax_Error("SQL Error", 1, 1, "Some text that failed or another C call returning a textual error message");
Hi Joseph,
thanks for your message. Just to make another test (I have done a million anyway) I have tried replacing
Pl_Exec_Continuation(a_throw, 1, &t);
with
Emit_Syntax_Error(...)
in my application (http://www.cs.unipr.it/ppl/) and I observe exactly the same segmentation violations and illegal instructions. May it be because Pl_Exec_Continuation is implemented by means of setjmp/longjmp and I am doing something that is incompatible with them? What can it be? Thanks again
Roberto

Fri, 2002-06-07 19:25, Roberto Bagnara wrote:
in my application (http://www.cs.unipr.it/ppl/) and I observe exactly the same segmentation violations and illegal instructions. May it be because Pl_Exec_Continuation is implemented by means of setjmp/longjmp and I am doing something that is incompatible with them? What can it be?
I hope not to bother anyone telling again that this problem seems very similar to the one I experienced with my applications using GTK. I found that such problems arise when linking code compiled without using frame pointer (like many distribution libraries) and gprolog compiled with all the default optimizations (among them the use of frame pointer). Problems actually appear just with callbacks in the case of GTK so I think your hypothesis could be right. I made some test in gdb discovering a complete mess in the stack after a call from a GTK callback. In some cases I could make things work by modifying manually the stack pointer. I discussed it with Daniel Diaz but I haven't had the time to test it thoroughly as Daniel asked me. My simple solution, so far, is to compile GNUProlog and the "critic" libraries or source-code all in the same way.
Bye, Daniele

Daniele Peri wrote:
Fri, 2002-06-07 19:25, Roberto Bagnara wrote:
in my application (http://www.cs.unipr.it/ppl/) and I observe exactly the same segmentation violations and illegal instructions. May it be because Pl_Exec_Continuation is implemented by means of setjmp/longjmp and I am doing something that is incompatible with them? What can it be?
I hope not to bother anyone telling again that this problem seems very similar to the one I experienced with my applications using GTK. I found that such problems arise when linking code compiled without using frame pointer (like many distribution libraries) and gprolog compiled with all the default optimizations (among them the use of frame pointer). Problems actually appear just with callbacks in the case of GTK so I think your hypothesis could be right. I made some test in gdb discovering a complete mess in the stack after a call from a GTK callback. In some cases I could make things work by modifying manually the stack pointer. I discussed it with Daniel Diaz but I haven't had the time to test it thoroughly as Daniel asked me. My simple solution, so far, is to compile GNUProlog and the "critic" libraries or source-code all in the same way.
Dear Daniele,
thanks for your message. Your analysis works! I use the GMP library which, by default, is compiled with -fomit-frame-pointer. And I use the PPL library (http://www.cs.unipr.it/ppl/) that, by default, is compiled without -fomit-frame-pointer. I have first tried to compile PPL with -fomit-frame-pointer and then I discovered the bug of GCC 3.0.x whereby C++ exceptions don't work with -fomit-frame-pointer.
Then I have tried compiling everything without -fomit-frame-pointer and everything works OK: I can throw C++ exceptions, catch them in C++ to convert them into GNU Prolog exceptions that can then correctly be caught by Prolog code.
I really feel this is a strong limitation of GNU Prolog: we cannot ask our users to recompile every library they use so as to make sure that -fomit-frame-pointer is used or left out consistently in all the builds. Daniel, do you envisage any solution to this problem? Can we do something to help? All the best
Roberto

I really feel this is a strong limitation of GNU Prolog: we cannot ask our users to recompile every library they use so as to make sure that -fomit-frame-pointer is used or left out consistently in all the builds.
One thing is that this option is among the ones which brings more speed (at least in ix86 architectures). Ciao Prolog is also compiled with this option.
MCL
________________________________________________________ In life, as in art, the truth is in the beholder's eyes.

Manuel Carro wrote:
I really feel this is a strong limitation of GNU Prolog: we cannot ask our users to recompile every library they use so as to make sure that -fomit-frame-pointer is used or left out consistently in all the builds.
One thing is that this option is among the ones which brings more
speed (at least in ix86 architectures). Ciao Prolog is also compiled with this option.
Right. However, I believe here the point is another one: do GNU and Ciao Prolog require all foreign code they interoperate with to be compiled with -fomit-frame-pointer for proper operation? And: to interoperate with foreign code compiled without -fomit-frame-pointer, is it necessary to recompile GNU and Ciao Prolog without -fomit-frame-pointer?
For GNU Prolog, the experiments conducted by Daniele and myself would seem to indicate two positive answers. Should that be confirmed, it would constitute a serious drawback of GNU Prolog, since proper behavior should not depend on how foreign code is compiled, provided the calling conventions of the platform at hand are respected (and compiling with or without -fomit-frame-pointer has no influence, AFAICT, on the calling conventions used in the platforms we are talking about). All the best
Roberto

Roberto Bagnara writes:
Right. However, I believe here the point is another one: do GNU and Ciao Prolog require all foreign code they interoperate with to be compiled with -fomit-frame-pointer for proper operation? And: to interoperate with foreign code compiled without -fomit-frame-pointer, is it necessary to recompile GNU and Ciao Prolog without -fomit-frame-pointer?
For GNU Prolog, the experiments conducted by Daniele and myself would seem to indicate two positive answers. Should that be confirmed, it would constitute a serious drawback of GNU Prolog, since proper behavior should not depend on how foreign code is compiled, provided the calling conventions of the platform at hand are respected (and compiling with or without -fomit-frame-pointer has no influence, AFAICT, on the calling conventions used in the platforms we are talking about).
It is possible that omiting the frame pointer (whose exact effect on the assembler output I really do not know) somehow affects the proper behavior of {long,set}jump. Note that this behavior is anyway not documented in the GCC manual --- maybe this kind of conduct is part of the lore in the C compiler arena.
Yes, we have interfaced with libraries (most probably) compiled without -fomit-frame-pointer, but as far as I remember we did not have to raise exceptions.
MCL

On 11-Jun-2002, Manuel Carro boris@aaron.ls.fi.upm.es wrote:
Roberto Bagnara writes:
Right. However, I believe here the point is another one: do GNU and Ciao Prolog require all foreign code they interoperate with to be compiled with -fomit-frame-pointer for proper operation? And: to interoperate with foreign code compiled without -fomit-frame-pointer, is it necessary to recompile GNU and Ciao Prolog without -fomit-frame-pointer?
For GNU Prolog, the experiments conducted by Daniele and myself would seem to indicate two positive answers. Should that be confirmed, it would constitute a serious drawback of GNU Prolog, since proper behavior should not depend on how foreign code is compiled, provided the calling conventions of the platform at hand are respected (and compiling with or without -fomit-frame-pointer has no influence, AFAICT, on the calling conventions used in the platforms we are talking about).
It is possible that omiting the frame pointer (whose exact effect
on the assembler output I really do not know) somehow affects the proper behavior of {long,set}jump. Note that this behavior is anyway not documented in the GCC manual --- maybe this kind of conduct is part of the lore in the C compiler arena.
Omitting the frame pointer should not have any effect on the behaviour of setjmp() and longjmp(). If it does, then that is a bug in GCC, which should be reported. But would be surprised by the existence of such a bug, since I have for quite some time been using setjmp() and longjmp() with GCC in code compiled with `-fomit-frame-pointer', without any problems.
The problem is more likely related to GNU Prolog's use of registers, IMHO.

On 11-Jun-2002, Fergus Henderson fjh@cs.mu.OZ.AU wrote:
On 11-Jun-2002, Manuel Carro boris@aaron.ls.fi.upm.es wrote:
It is possible that omiting the frame pointer (whose exact effect
on the assembler output I really do not know) somehow affects the proper behavior of {long,set}jump. Note that this behavior is anyway not documented in the GCC manual --- maybe this kind of conduct is part of the lore in the C compiler arena.
Omitting the frame pointer should not have any effect on the behaviour of setjmp() and longjmp(). If it does, then that is a bug in GCC, which should be reported.
Sorry, I should have said "a bug in GCC and/or glibc".
Also note that the behaviour of longjmp() and setjmp() is documented in the C standard, and in the glibc manual -- that's why there's no need to document it in the GCC manual.

Hi everybody,
Fergus is right, GNU Prolog uses ebp to map a WAM register in a physical register (to increase efficiency). Since ebp serves as frame pointer, the code using WAM internals should be compiled with -fomit-frame-pointer. Other code CAN use ebp (since ebp is saved/restored in called functions). But a foreign code needs to be compiled withth -fomit-frame-pointer (and also -O2 or -O3).
Obviously this can be a problem for people using a precompiled version + foreign code. However, it is not really difficult to compile a customized version of GNU Prolog, in our case:
./configure --disable-ebp make make install
This is really not difficult (specially for people writing foreing code).
I could also proposes 2 precompiled versions (one with ebp and another one without ebp) but it is a bit heavy for me to always ensure both are well produced. Finally I could only produce binaires with --disable-ebp...
Fergus Henderson wrote:
On 11-Jun-2002, Manuel Carro boris@aaron.ls.fi.upm.es wrote:
Roberto Bagnara writes:
Right. However, I believe here the point is another one: do GNU and Ciao Prolog require all foreign code they interoperate with to be compiled with -fomit-frame-pointer for proper operation? And: to interoperate with foreign code compiled without -fomit-frame-pointer, is it necessary to recompile GNU and Ciao Prolog without -fomit-frame-pointer?
For GNU Prolog, the experiments conducted by Daniele and myself would seem to indicate two positive answers. Should that be confirmed, it would constitute a serious drawback of GNU Prolog, since proper behavior should not depend on how foreign code is compiled, provided the calling conventions of the platform at hand are respected (and compiling with or without -fomit-frame-pointer has no influence, AFAICT, on the calling conventions used in the platforms we are talking about).
It is possible that omiting the frame pointer (whose exact effect
on the assembler output I really do not know) somehow affects the proper behavior of {long,set}jump. Note that this behavior is anyway not documented in the GCC manual --- maybe this kind of conduct is part of the lore in the C compiler arena.
Omitting the frame pointer should not have any effect on the behaviour of setjmp() and longjmp(). If it does, then that is a bug in GCC, which should be reported. But would be surprised by the existence of such a bug, since I have for quite some time been using setjmp() and longjmp() with GCC in code compiled with `-fomit-frame-pointer', without any problems.
The problem is more likely related to GNU Prolog's use of registers, IMHO.
-- Fergus Henderson fjh@cs.mu.oz.au | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: http://www.cs.mu.oz.au/~fjh | -- the last words of T. S. Garp.
Users-prolog mailing list Users-prolog@gnu.org http://mail.gnu.org/mailman/listinfo/users-prolog

On 11-Jun-2002, Daniel Diaz Daniel.Diaz@univ-paris1.fr wrote:
Fergus is right, GNU Prolog uses ebp to map a WAM register in a physical register (to increase efficiency). Since ebp serves as frame pointer, the code using WAM internals should be compiled with -fomit-frame-pointer. Other code CAN use ebp (since ebp is saved/restored in called functions). But a foreign code needs to be compiled withth -fomit-frame-pointer (and also -O2 or -O3).
Using `-fomit-frame-pointer' (with or without -O2/-O3) is not sufficient to guarantee that the generated code won't use the `ebp' register. The `-fomit-frame-pointer' option tells GCC to omit a frame pointer where possible, but it's not always possible. In particular, code using variable-length arrays or alloca() always needs a frame pointer. There may also be other circumstances in which a frame pointer is required.
While it's OK to avoid using such features in the code for GNU Prolog itself, I don't think it's a good idea to rely on third-party C libraries not using ebp when they are compiled with -fomit-frame-pointer. That would lead to code which might break when the third-party C library is upgraded to the next version.
I think it would be better for GNU Prolog to save/restore ebp itself, either in the code for handling exceptions, or when calling foreign code. (However, I'm not that familiar with the internals of GNU Prolog, so I don't know how feasible this would be.)

Fergus Henderson wrote:
On 11-Jun-2002, Daniel Diaz Daniel.Diaz@univ-paris1.fr wrote:
Fergus is right, GNU Prolog uses ebp to map a WAM register in a physical register (to increase efficiency). Since ebp serves as frame pointer, the code using WAM internals should be compiled with -fomit-frame-pointer. Other code CAN use ebp (since ebp is saved/restored in called functions). But a foreign code needs to be compiled withth -fomit-frame-pointer (and also -O2 or -O3).
Using `-fomit-frame-pointer' (with or without -O2/-O3) is not sufficient to guarantee that the generated code won't use the `ebp' register. The `-fomit-frame-pointer' option tells GCC to omit a frame pointer where possible, but it's not always possible. In particular, code using variable-length arrays or alloca() always needs a frame pointer. There may also be other circumstances in which a frame pointer is required.
True, e.e. recently gcc 3.0.3 used a frame pointer for the main function (to adjust stack boundary).
While it's OK to avoid using such features in the code for GNU Prolog itself, I don't think it's a good idea to rely on third-party C libraries not using ebp when they are compiled with -fomit-frame-pointer. That would lead to code which might break when the third-party C library is upgraded to the next version.
Not really because if this third-party uses ebp it will then save it at the entry and restore it at the exit. So the problem comes from foreign code using a frame pointer (i.e. ebp) and calling a GNU-Prolog library function expecting ebp contains a valid WAM register.
I think it would be better for GNU Prolog to save/restore ebp itself, either in the code for handling exceptions, or when calling foreign code. (However, I'm not that familiar with the internals of GNU Prolog, so I don't know how feasible this would be.)
-- Fergus Henderson fjh@cs.mu.oz.au | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: http://www.cs.mu.oz.au/~fjh | -- the last words of T. S. Garp.
Users-prolog mailing list Users-prolog@gnu.org http://mail.gnu.org/mailman/listinfo/users-prolog

On 12-Jun-2002, Daniel Diaz Daniel.Diaz@univ-paris1.fr wrote:
Fergus Henderson wrote:
Using `-fomit-frame-pointer' (with or without -O2/-O3) is not sufficient to guarantee that the generated code won't use the `ebp' register. [...] I don't think it's a good idea to rely on third-party C libraries not using ebp when they are compiled with -fomit-frame-pointer. That would lead to code which might break when the third-party C library is upgraded to the next version.
Not really because if this third-party uses ebp it will then save it at the entry and restore it at the exit. So the problem comes from foreign code using a frame pointer (i.e. ebp) and calling a GNU-Prolog library function expecting ebp contains a valid WAM register.
I understand that. But IMHO the external interface that GNU-Prolog presents to C code should not rely on ebp containing a valid WAM register. Instead, GNU-Prolog should save ebp (to a global or thread-local variable) before calling foreign code, and the routines in the external interface presented to C code should restore ebp (from the global or thread-local variable) before trying to access it. Likewise for any other registers.
That's what we do in the Mercury implementation.
participants (5)
-
Daniel Diaz
-
Daniele Peri
-
Fergus Henderson
-
Manuel Carro
-
Roberto Bagnara