Hi there, I've been doing a lot of work with GiNaC recently but just now I think I have a problem which relates more specifically with CLN, so hopefully I'm asking this question in the right place. I have had a few problems now with CLN's error handling: it tends to just abort when something goes wrong. Is there a reason why it doesn't just throw exceptions that I can catch?
void cl_error_floating_point_nan (void) { fprint(std::cerr, "floating point NaN occurred.\n"); cl_abort(); }
I can see that I could rewrite the 'cl_abort' function so that it does throw exceptions, but I just wanted to point out that CLN is a big job to compile and it might be nice if it gives this sort of functionality out-of-the-box. I can't use the suggested method from the manual either,
The library does type checks, range checks, consistency checks at many places. When one of these fails, the function |cl_abort()| is called. Its default implementation is to perform an |exit(1)|, so you won't have a core dump. But for debugging, it is best to set a breakpoint at this function:
(gdb) break cl_abort
When this breakpoint is hit, look at the stack's backtrace:
(gdb) where
because my pre-compiled CLN doesn't seem to have debug symbols:
[john@jdpipe nla-ginac]$ gdb pipesystem GNU gdb Red Hat Linux (6.1post-1.20040607.43rh)
...
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) break cl_abort Function "cl_abort" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (cl_abort) pending. (gdb) run Starting program: /home/john/nla-ginac/pipesystem Reading symbols from shared object read from target memory...done. Loaded system supplied DSO at 0xb7f9f000
...
floating point NaN occurred.
Program exited with code 01. (gdb) where No stack.
So, I'd like to suggest replacing cl_abort with either a SIGFPE or a standard exception of some sort. But please, if there are other issues at hand, or reasons why you don't do things that way, I'd be keen to know. Cheers JP
Dear John, On Thu, 28 Jul 2005, John Pye wrote:
I've been doing a lot of work with GiNaC recently but just now I think I have a problem which relates more specifically with CLN, so hopefully I'm asking this question in the right place.
I have had a few problems now with CLN's error handling: it tends to just abort when something goes wrong. Is there a reason why it doesn't just throw exceptions that I can catch?
void cl_error_floating_point_nan (void) { fprint(std::cerr, "floating point NaN occurred.\n"); cl_abort(); }
I can see that I could rewrite the 'cl_abort' function so that it does throw exceptions, but I just wanted to point out that CLN is a big job to compile and it might be nice if it gives this sort of functionality out-of-the-box.
I've also become somewhat unsatisfied with that scheme, lately. But I haven't found the time to dig into this. Question: What exactly happens when you throw an exception from within a library that was compiled with -fno-exceptions?
I can't use the suggested method from the manual either, [...] because my pre-compiled CLN doesn't seem to have debug symbols:
Of course not: when I last compiled it with -g the size of the library exceeded 64MB. I'm not enthusiastic about shipping precompiled lib of this size.
So, I'd like to suggest replacing cl_abort with either a SIGFPE or a standard exception of some sort.
I don't see how SIGFPE would help you with the "no stack" problem. And before compiling it with exceptions I would be interested in the overhead this incurs, especially in the stack unwinding code that comes with dtors.
But please, if there are other issues at hand, or reasons why you don't do things that way, I'd be keen to know.
The list of reasons above is complete, I think. Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hi Richy So it looks like the main issue is the overhead of processing the exceptions through destructors in CLN. I made a simple change to one or two lines in the cl_abort.cc file such that it now throws runtime_error("CLN error"); This has been adequate for me to get good information back from GDB. My applications of CLN are perhaps not typical; I'm using GiNaC to implement a fairly basic non-linear solver with a possible view to adding DAE solver capabilities at some point. So the CLN speed is not so critical at this stage; more likely my immediate bottleneck will be in other areas related to dense matrix manipulation in a fortan library I'm using. What's more importantant is that I can quickly track down the source of my coding erros. I didn't compile CLN originally, I downloaded an RPM for FC3 i386, latest CLN, GiNaC 1.3.1. from 'pbone' RPM repository. I've now compiled CLN with my changes and created a new RPM but I'm still using the standard GiNaC which I downloaded. If you want to try to build CLN with exceptions as I have, you can use the attached RPM spec & patch file, if you wish. As you can see, there is no special 'configure' call, just the patch which I applied. A more rigorous approach would be to add specialised 'throws' depending on the error which occurred (throw cln_nan_error(), etc?); my patch is minimal. As for -fno-exceptions, I don't know about that compiler directive. Does G++ insert "abort" calls in place of "throw" calls if you use that? I can see that you have a difficult balance between speed and userfriendliness to decide on here. I might have been wrong about SIGFPE. I thought that under such cases a stack dump might be generated, which could be used to locate the error. Mistaken in that? Cheers JP Richard B. Kreckel wrote:
Dear John,
On Thu, 28 Jul 2005, John Pye wrote:
I've been doing a lot of work with GiNaC recently but just now I think I have a problem which relates more specifically with CLN, so hopefully I'm asking this question in the right place.
I have had a few problems now with CLN's error handling: it tends to just abort when something goes wrong. Is there a reason why it doesn't just throw exceptions that I can catch?
void cl_error_floating_point_nan (void) { fprint(std::cerr, "floating point NaN occurred.\n"); cl_abort(); }
I can see that I could rewrite the 'cl_abort' function so that it does throw exceptions, but I just wanted to point out that CLN is a big job to compile and it might be nice if it gives this sort of functionality out-of-the-box.
I've also become somewhat unsatisfied with that scheme, lately. But I haven't found the time to dig into this. Question: What exactly happens when you throw an exception from within a library that was compiled with -fno-exceptions?
I can't use the suggested method from the manual either,
[...]
because my pre-compiled CLN doesn't seem to have debug symbols:
Of course not: when I last compiled it with -g the size of the library exceeded 64MB. I'm not enthusiastic about shipping precompiled lib of this size.
So, I'd like to suggest replacing cl_abort with either a SIGFPE or a standard exception of some sort.
I don't see how SIGFPE would help you with the "no stack" problem. And before compiling it with exceptions I would be interested in the overhead this incurs, especially in the stack unwinding code that comes with dtors.
But please, if there are other issues at hand, or reasons why you don't do things that way, I'd be keen to know.
The list of reasons above is complete, I think.
Regards -richy.
diff -uNr cln-1.1.9-orig/src/base/cl_abort.cc cln-1.1.9/src/base/cl_abort.cc --- cln-1.1.9-orig/src/base/cl_abort.cc 2005-07-28 11:12:59.000000000 +1000 +++ cln-1.1.9/src/base/cl_abort.cc 2005-07-28 11:26:47.000000000 +1000 @@ -6,6 +6,7 @@ // Specification. #include "cln/abort.h" +#include <stdexcept> // Implementation. @@ -15,7 +16,8 @@ void cl_abort (void) { - exit(1); + throw std::runtime_error("CLN error"); + //exit(1); } } // namespace cln Name: cln Version: 1.1.9 Release: 1.jdpipe Summary: Class Library for Numbers Group: System Environment/Libraries License: GPL URL: http://www.ginac.de/CLN/ Source0: ftp://ftpthep.physik.uni-mainz.de/pub/gnu/%{name}-%{version}.tar.bz2 Patch0: http://pye.dyndns.org/%{name}-%{version}.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires(post): /sbin/install-info Requires(preun): /sbin/install-info BuildRequires: gmp-devel %description A collection of C++ math classes and functions, which are designed for memory and speed efficiency, and enable type safety and algebraic syntax. %package devel Summary: Development files for programs using the CLN library Group: Development/Libraries Requires: %{name} = %{version}-%{release} gmp-devel %description devel A collection of C++ math classes and functions, which are designed for memory and speed efficiency, and enable type safety and algebraic syntax. This package is necessary if you wish to develop software based on the CLN library. %prep %setup -q %patch -p 1 %build %configure make %install rm -rf ${RPM_BUILD_ROOT} %makeinstall mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}-devel-%{version} mv ${RPM_BUILD_ROOT}%{_datadir}/dvi/cln.dvi ${RPM_BUILD_ROOT}%{_datadir}/html ${RPM_BUILD_ROOT}%{_docdir}/%{name}-devel-%{version} %clean rm -rf ${RPM_BUILD_ROOT} %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %post devel /sbin/install-info --section="Math" %{_infodir}/cln.info.gz %{_infodir}/dir 2>/dev/null || : %preun devel if [ "$1" = 0 ]; then /sbin/install-info --delete %{_infodir}/cln.info.gz %{_infodir}/dir 2>/dev/null || : fi %files %defattr(-,root,root) %doc COPYING ChangeLog FILES NEWS README TODO* %{_libdir}/*.so.* %files devel %defattr(-,root,root) %{_docdir}/%{name}-devel-%{version} %{_libdir}/*.a %{_libdir}/*.so %{_libdir}/pkgconfig/cln.pc %{_includedir}/cln/ %{_infodir}/*.info* %{_mandir}/man1/cln-config.1* %{_bindir}/cln-config %{_datadir}/aclocal/cln.m4 %exclude %{_libdir}/*.la %changelog * Fri Jul 29 2005 John Pye <john.pye@student.unsw.edu.au> 1.1.9-1.jdpipe - Patched to provide exceptions rather than abort when FPEs occur * Fri May 27 2005 Quentin Spencer <qspencer@users.sf.net> 1.1.9-3 - Added gmp-devel to Requires for devel * Fri May 20 2005 Quentin Spencer <qspencer@users.sf.net> 1.1.9-2 - Added dist tag. * Wed May 11 2005 Quentin Spencer <qspencer@users.sf.net> 1.1.9-1 - Excluded .la file * Fri Apr 22 2005 Quentin Spencer <qspencer@users.sf.net> 1.1.9-1 - Added gmp-devel in BuildRequires, fixes in files - Added release to name in Requires for devel * Mon Mar 21 2005 Quentin Spencer <qspencer@users.sf.net> 1.1.9-1 - Adapted spec file for Fedora Extras * Thu Nov 20 2003 Christian Bauer <Christian.Bauer@uni-mainz.de> Added pkg-config metadata file to devel package * Wed Nov 6 2002 Christian Bauer <Christian.Bauer@uni-mainz.de> Added HTML and DVI docs to devel package * Tue Nov 5 2001 Christian Bauer <Christian.Bauer@uni-mainz.de> Added Packager
John Pye wrote:
I can't use the suggested method from the manual either,
The library does type checks, range checks, consistency checks at many places. When one of these fails, the function |cl_abort()| is called. Its default implementation is to perform an |exit(1)|, so you won't have a core dump. But for debugging, it is best to set a breakpoint at this function:
(gdb) break cl_abort
When this breakpoint is hit, look at the stack's backtrace:
(gdb) where
because my pre-compiled CLN doesn't seem to have debug symbols:
[john@jdpipe nla-ginac]$ gdb pipesystem GNU gdb Red Hat Linux (6.1post-1.20040607.43rh)
...
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) break cl_abort Function "cl_abort" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (cl_abort) pending. (gdb) run Starting program: /home/john/nla-ginac/pipesystem Reading symbols from shared object read from target memory...done. Loaded system supplied DSO at 0xb7f9f000
The following often works better than the method you tried: (gdb) break main (gdb) run Breakpoint main reached (gdb) break cl_abort (gdb) continue Breakpoint cl_abort reached Or, if that doesn't work, try the same with 'exit' instead of 'cl_abort'. If that works but (gdb) break cl_abort then try this: (gdb) set language c++ (gdb) break cl_abort
So, I'd like to suggest replacing cl_abort with either a SIGFPE or a standard exception of some sort.
We chose not to make a SIGFPE or SIGABRT out of it, since it usually creates a core dump, whose size is often > 10 MB. We also chose not to make it an exception, so that cln could be compiled with -fno-exceptions (useful when g++ creates horrible code otherwise). Bruno
participants (3)
-
Bruno Haible
-
John Pye
-
Richard B. Kreckel