Version 0.90

master
Marc Wäckerlin 21 years ago
parent e303138fcd
commit 93696ef645
  1. 18
      COPYING
  2. 7
      ChangeLog
  3. 5
      NEWS
  4. 15
      README
  5. 4
      bootstrap.sh
  6. 31
      configure.in
  7. 23
      makefile.am
  8. 42
      mrw-c++-devel.spec.in
  9. 46
      mrw-c++.spec.in
  10. 4
      mrw/auto.hpp
  11. 91
      mrw/autostacktracelog4cxx.cpp
  12. 70
      mrw/autostacktracestderr.cpp
  13. 30
      mrw/doxyfile.in
  14. 55
      mrw/examples/exceptionhandling.cpp
  15. 10
      mrw/exception.hpp
  16. 24
      mrw/exec.cpp
  17. 7
      mrw/exec.hpp
  18. 29
      mrw/makefile.am
  19. 65
      mrw/mrw.hpp.in
  20. 68
      mrw/mrwexclog4cxx_test.cpp
  21. 66
      mrw/mrwexcstderr_test.cpp
  22. 38
      mrw/stacktrace.hpp
  23. 6
      mrw/unistd.hpp

@ -57,7 +57,7 @@ modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
^L
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
@ -113,7 +113,7 @@ modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
^L
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@ -160,7 +160,7 @@ Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
@ -218,7 +218,7 @@ instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
^L
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
@ -269,7 +269,7 @@ Library will still fall under Section 6.)
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
^L
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
@ -331,7 +331,7 @@ restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
^L
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
@ -372,7 +372,7 @@ subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
^L
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
@ -425,7 +425,7 @@ conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
^L
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
@ -459,7 +459,7 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
^L
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest

@ -0,0 +1,7 @@
* Fri Apr 24 2004 Marc Wäckerlin <marc@waeckerlin.org> - mrw-c++-0.90 (mrw)
- initial rpm with two spec files
- test cases for libmrwexcstderr and libmrwexclog4cxx
* Thu Apr 23 2004 Marc Wäckerlin <marc@waeckerlin.org> - mrw-c++-0.11 (mrw)
- better support for solaris, but not yet tested
- more and better documentation and a pdf file
- new submodule "Automated Unexpected Handler with Stack Trace"

@ -0,0 +1,5 @@
This is a preliminary release. Especially tests, configure
environment, packages and documentation are not yet finished. It
should already work, even though it may be not yet perfect.
It is know not to link on Solaris.

@ -1,9 +1,6 @@
Please read:
- from the .tar.gz package:
mrw/doc/html/index.html
- from the .tar.gz installation:
/usr/local/share/mrw-c++/doc/html/index.html
- from the rpm installation:
/usr/share/doc/packages/mrw-c++/doc/html/index.html
- the webpage at:
http://marc.waeckerlin.org/mrw-c++/index.html
C++ Library for automated C-Library resource management, UNIX
Pipes, simple and secure UNIX system command execution, runtime
stack trace and automated unexpected exception handling.
HTML and PDF documentation is include in the installation (built with
Doxygen).

@ -0,0 +1,4 @@
#! /bin/sh
make distclean
aclocal && libtoolize --force && automake && autoconf

@ -1,9 +1,16 @@
AC_INIT([mrw/stacktrace.hpp])
# init
AC_INIT([mrw/mrw.hpp.in])
PACKAGENAME=mrw-c++
MAJOR=0
MINOR=10
SUPPORT=alfa
AM_INIT_AUTOMAKE(@PACKAGENAME@, @MAJOR@.@MINOR@)
MINOR=90
SUPPORT=beta
AM_INIT_AUTOMAKE(@PACKAGENAME@, @MAJOR@.@MINOR@, [marc@waeckerlin.org])
# macros
README=README
AC_SUBST_FILE(README)
CHANGE_LOG=ChangeLog
AC_SUBST_FILE(CHANGE_LOG)
# languages
AC_LANG(C++)
@ -18,9 +25,18 @@ AC_PROG_LIBTOOL
AC_CHECK_PROG(have_doxygen, doxygen, yes, no)
AC_CHECK_PROG(have_dot, dot, yes, no)
# solaris?
AC_CHECK_HEADER(sys/old_procfs.h, [AM_CPPFLAGS=-D__solaris__])
# libraries
AC_SEARCH_LIBS(cplus_demangle, iberty)
AC_SEARCH_LIBS(bfd_get_symbol_leading_char, bfd)
AC_SEARCH_LIBS(cplus_demangle, iberty, [AC_MSG_RESULT([OK])],
[AC_MSG_ERROR([Library iberty is required!])])
AC_SEARCH_LIBS(bfd_arch_list, bfd, [AC_MSG_RESULT([OK])],
[
AC_SEARCH_LIBS(bfd_arch_list, bfd, [AC_MSG_RESULT([OK])],
[AC_MSG_ERROR([BFD library libbfd is required])],
[-lintl])
])
# Arguments
AM_MAINTAINER_MODE
@ -37,7 +53,8 @@ AC_SUBST(SUPPORT)
AC_SUBST(PACKAGENAME)
# create output
AC_CONFIG_FILES([makefile mrw/makefile mrw/doxyfile mrw/mrw.hpp])
AC_CONFIG_FILES([makefile mrw-c++.spec mrw-c++-devel.spec
mrw/makefile mrw/doxyfile mrw/mrw.hpp])
AC_OUTPUT
# infos and warnings

@ -1,11 +1,24 @@
SUBDIRS = mrw
include_HEADERS = mrw/auto.hpp mrw/unistd.hpp \
nobase_include_HEADERS = mrw/auto.hpp mrw/unistd.hpp \
mrw/stacktrace.hpp mrw/exception.hpp \
mrw/exec.hpp
data_DATA = AUTHORS NEWS README COPYING INSTALL ChangeLog
infosdir = ${pkgdatadir}
infos_DATA = AUTHORS NEWS README COPYING INSTALL ChangeLog \
@PACKAGENAME@.spec @PACKAGENAME@-devel.spec
webserver: all check doc dist
RPMS = /usr/src/packages/RPMS/i586/@PACKAGENAME@-@MAJOR@.@MINOR@-1.i586.rpm \
/usr/src/packages/RPMS/i586/@PACKAGENAME@-devel-@MAJOR@.@MINOR@-1.i586.rpm
rpm: dist
cp @PACKAGENAME@-@MAJOR@.@MINOR@.tar.gz /usr/src/packages/SOURCES/
rpmbuild -bb --clean @PACKAGENAME@.spec
rpmbuild -bb --clean @PACKAGENAME@-devel.spec
webserver: all check dist ${RPMS}
ssh root@waeckerlin.org mkdir -p /home/marc/mrw-c++
scp mrw/doc/html/* root@waeckerlin.org:/home/marc/mrw-c++/
scp @PACKAGENAME@-@MAJOR@.@MINOR@.tar.gz root@waeckerlin.org:/home/marc/mrw-c++/
scp mrw/doc/html/* \
mrw/doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf \
@PACKAGENAME@-@MAJOR@.@MINOR@.tar.gz \
${RPMS} \
root@waeckerlin.org:/home/marc/mrw-c++/

@ -0,0 +1,42 @@
# rpmbuild -bb --clean @PACKAGENAME@.spec
Summary: MRW's C++ Class Library, facilities for ease and quality
Name: @PACKAGENAME@-devel
Version: @MAJOR@.@MINOR@
Release: 1
License: LGPL
Group: Development/Libraries/C++
URL: http://marc.waeckerlin.org/mrw-c++/index.html
Source0: @PACKAGENAME@-@MAJOR@.@MINOR@.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: /usr
Requires: gcc-c++ >= 3.0
Requires: binutils
Requires: @PACKAGENAME@ = @MAJOR@.@MINOR@
%description
@README@
This Package contains all files required for developement.
%prep
%setup -q -n @PACKAGENAME@-@MAJOR@.@MINOR@
./configure --prefix=$RPM_BUILD_ROOT/usr
%build
make check
%install
make install
rm -rf $RPM_BUILD_ROOT/usr/lib/libmrw*.so*
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
/usr
%changelog
@CHANGE_LOG@

@ -0,0 +1,46 @@
# rpmbuild -bb --clean @PACKAGENAME@.spec
Summary: MRW's C++ Class Library, facilities for ease and quality
Name: @PACKAGENAME@
Version: @MAJOR@.@MINOR@
Release: 1
License: LGPL
Group: Development/Libraries/C++
URL: http://marc.waeckerlin.org/mrw-c++/index.html
Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
Prefix: /usr
Requires: gcc-c++ >= 3.0
Requires: binutils
%description
@README@
This package contains only the shared libraries required at runtime.
%prep
%setup -q
./configure --prefix=$RPM_BUILD_ROOT/usr
%build
make check
%install
make install
rm -rf $RPM_BUILD_ROOT/usr/share/mrw-c++
rm -rf $RPM_BUILD_ROOT/usr/include/mrw
rm -rf $RPM_BUILD_ROOT/usr/lib/libmrw*.la
rm -rf $RPM_BUILD_ROOT/usr/lib/libmrw*.a
rmdir $RPM_BUILD_ROOT/usr/include
rmdir $RPM_BUILD_ROOT/usr/share
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
/usr
%changelog
@CHANGE_LOG@

@ -19,6 +19,7 @@ namespace mrw {
//@{
/** @brief Automatically closes a file when destructed.
@pre #include <mrw/auto.hpp>
AutoFile works exactly like std::auto_ptr, but not for files
instead of pointers. Whenever the context of AutoFile is left,
@ -59,6 +60,7 @@ namespace mrw {
};
/** @brief Automatically call @c munmap for mmaped files on destruction.
@pre #include <mrw/auto.hpp>
It's the same as std::auto_ptr, but for @c mmap instead of @c
new. When the context of @c AutoMapper is left, @c munmap is
@ -89,6 +91,7 @@ namespace mrw {
};
/** @brief Automatically call @c bfd_close for @c bfd*.
@pre #include <mrw/auto.hpp>
It acts like a @c std::auto_ptr, but for @c bfd*, that means it
calls @c bfd_close whenever the context is left.
@ -111,6 +114,7 @@ namespace mrw {
};
/** @brief Automatically calls @c free for @c malloc allocated memory.
@pre #include <mrw/auto.hpp>
It works like a @c std::auto_ptr, but for memory that was
allocated with @c malloc, not @c new. Memory is freed, whenever

@ -0,0 +1,91 @@
#include <mrw/stacktrace.hpp>
#include <mrw/exception.hpp>
#include <exception>
#include <log4cxx/logger.h>
namespace mrw {
/** @addtogroup StackTrace */
//@{
/** @addtogroup AutoTrace
@section trclog4cxx Trace using the log4cxx Library
If you link to the library @c libmrwexclog4cxx using a linker
option such as: @c -lmrwexclog4cxx, then an unexpected handler
is registered, that traces a fatal error using the log4cxx
library. You don't need to change a single line in your code!
The log4cxx library is located at:
- http://logging.apache.org/log4cxx
@note The configurator is not installed automatically. If you
want to trace e.g. on the console, you have to call @c
log4cxx::BasicConfigurator::configure(); as first statement in
your @c main().
*/
//@{
/// The log4cxx logger where the trace is written to.
static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("libmrw"));
/** @brief unexpected handler, that traces using log4cxx
The unexpected handler is installed automatically when you link
to @c -lmrwexclog4cxx. The implementation of this unexpected
handler is as follows:
@code
void unexpected_log4cxx() {
logger->fatal("Unexpected Exception", __FILE__, __LINE__);
try {
throw;
} catch (const mrw::exception& x) {
StackTrace::createSymtable();
logger->fatal(std::string("Reason:\n")+x.what()
+"\nStack:+\n"+x.stacktrace());
} catch (const std::exception& x) {
logger->fatal(std::string("Reason:\n")+x.what()
+"\nStack: **** not available ****");
} catch (...) {
logger->fatal(std::string("Reason: **** not available ****\n")
+"\nStack: **** not available ****");
}
throw std::bad_exception();
}
@endcode
*/
void unexpected_log4cxx() {
logger->fatal("Unexpected Exception", __FILE__, __LINE__);
try {
throw;
} catch (const mrw::exception& x) {
StackTrace::createSymtable();
logger->fatal(std::string("Reason:\n")+x.what()
+"\nStack:+\n"+x.stacktrace());
} catch (const std::exception& x) {
logger->fatal(std::string("Reason:\n")+x.what()
+"\nStack: **** not available ****");
} catch (...) {
logger->fatal(std::string("Reason: **** not available ****\n")
+"\nStack: **** not available ****");
}
throw std::bad_exception();
}
//@}
//@}
class AutoStackTrace {
public:
AutoStackTrace() {
std::set_unexpected(&mrw::unexpected_log4cxx);
}
};
// initialize stack traces (load symbols)
static AutoStackTrace _autoStackTrace;
}

@ -5,8 +5,45 @@
namespace mrw {
/// @todo integrate it into the distribution and document it
void unexpected() {
/** @addtogroup StackTrace */
//@{
/** @defgroup AutoTrace Automated Unexpected Handler with Stack Trace
@brief Don't care about the unexpected handler, let the library
do all the repetitive work for you.
For all your programs it is recommended to implement an identical
unexpected handler, that rethrows, catches the @c
mrw::exception, @c std::exception and all unknown exceptions,
traces them and finally quits with a throw of a @c
atd::bad_exception. The only thing that may be different from
project to project is, how tracing is done. The MRW C++ Class
Library provides you with additional libraries you can link
to. By linking to the library, you get an unexpected handler for
free: You don't need to add a single line of code, just link to
one more library! The libraries differ in how tracing is done.
The Implementation is done with a static instance of a class that
sets the unexpected handler in the constructor.
@section trcstderr Trace using std::cerr
If you link to the library @c libmrwexcstderr using a linker
option such as: @c -lmrwexcstderr, then an unexpected handler is
registered, that traces to the standard error stream @c
std::cerr. You don't need to change a single line in your code!
*/
//@{
/** @brief unexpected handler, that traces to @c std::cerr
The unexpected handler is installed automatically when you link
to @c -lmrwexcstderr. The implementation of this unexpected
handler is as follows:
@code
void unexpected_stderr() {
std::cerr<<"UNEXPECTED EXCEPTION: ----------------------------"<<std::endl;
try {
throw;
@ -27,11 +64,38 @@ namespace mrw {
std::cerr<<"-------------------------------------------------"<<std::endl;
throw std::bad_exception();
}
@endcode
*/
void unexpected_stderr() {
std::cerr<<"UNEXPECTED EXCEPTION: ----------------------------"<<std::endl;
try {
throw;
} catch (const mrw::exception& x) {
StackTrace::createSymtable();
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack:"<<std::endl
<<x.stacktrace()<<std::endl;
} catch (const std::exception& x) {
std::cerr<<"---------- Reason:"<<std::endl
<<x.what()<<std::endl
<<"---------- Stack: **** not available ****"<<std::endl;
} catch (...) {
std::cerr<<"---------- Reason: **** not available ****"<<std::endl
<<"---------- Stack: **** not available ****"<<std::endl;
}
std::cerr<<"-------------------------------------------------"<<std::endl;
throw std::bad_exception();
}
//@}
//@}
class AutoStackTrace {
public:
AutoStackTrace() {
std::set_unexpected(&mrw::unexpected);
std::set_unexpected(&mrw::unexpected_stderr);
}
};

@ -117,7 +117,7 @@ BRIEF_MEMBER_DESC = YES
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
REPEAT_BRIEF = NO
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
@ -143,7 +143,7 @@ FULL_PATH_NAMES = YES
# only done if one of the specified strings matches the left-hand part of
# the path. It is allowed to use relative paths in the argument list.
STRIP_FROM_PATH = ../
STRIP_FROM_PATH = ..
# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
@ -176,7 +176,7 @@ HIDE_SCOPE_NAMES = NO
# will put a list of the files that are included by a file in the documentation
# of that file.
SHOW_INCLUDE_FILES = YES
SHOW_INCLUDE_FILES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
@ -297,7 +297,7 @@ OPTIMIZE_OUTPUT_JAVA = NO
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.
SHOW_USED_FILES = YES
SHOW_USED_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
@ -381,13 +381,13 @@ EXCLUDE_SYMLINKS = NO
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
EXCLUDE_PATTERNS =
EXCLUDE_PATTERNS = *_test.cpp
# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH = examples ..
EXAMPLE_PATH = .. examples
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@ -602,7 +602,7 @@ TREEVIEW_WIDTH = 250
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = NO
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
@ -625,7 +625,7 @@ MAKEINDEX_CMD_NAME = makeindex
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
COMPACT_LATEX = YES
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
@ -650,26 +650,26 @@ LATEX_HEADER =
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
LATEX_BATCHMODE = YES
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
LATEX_HIDE_INDICES = YES
#---------------------------------------------------------------------------
# configuration options related to the RTF output
@ -691,7 +691,7 @@ RTF_OUTPUT = rtf
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_RTF = NO
COMPACT_RTF = YES
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
@ -700,7 +700,7 @@ COMPACT_RTF = NO
# programs which support those fields.
# Note: wordpad (write) and others do not support links.
RTF_HYPERLINKS = NO
RTF_HYPERLINKS = YES
# Load stylesheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assigments. You only have to provide
@ -739,7 +739,7 @@ MAN_EXTENSION = .3
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = NO
MAN_LINKS = YES
#---------------------------------------------------------------------------
# configuration options related to the XML output

@ -0,0 +1,55 @@
#include <mrw/exception.hpp>
#include <mrw/stacktrace.hpp>
#include <exception>
#include <iostream>
void unexpectedHandler() {
try {
throw;
} catch (mrw::exception& x) {
mrw::StackTrace::createSymtable();
std::cerr<<"UNEXPECTED:"<<x.what()<<std::endl
<<"---------------------------Stack:"<<std::endl
<<x.stacktrace()
<<"---------------------------------"<<std::endl;
} catch (std::exception& x) {
std::cerr<<"UNEXPECTED:"<<x.what()<<std::endl;
} catch (...) {
std::cerr<<"UNKNOWN UNEXPECTED"<<std::endl;
}
throw std::bad_exception(); // try to recover
}
void fn2() throw(std::bad_exception) {
std::cout<<"enter fn2"<<std::endl;
throw mrw::exception(); // that's wrong, no exception excpected
std::cout<<"leave fn2"<<std::endl;
}
void fn1() throw(std::bad_exception) {
std::cout<<"enter fn1"<<std::endl;
fn2();
std::cout<<"leave fn1"<<std::endl;
}
void fn0() throw(std::bad_exception) {
std::cout<<"enter fn0"<<std::endl;
try {
fn1();
} catch (std::exception& x) {
std::cerr<<"EXCEPTION caught in fn0:"<<x.what()<<std::endl;
}
std::cout<<"leave fn0"<<std::endl;
}
int main() {
std::set_unexpected(&unexpectedHandler);
try {
std::cout<<"call fn0"<<std::endl;
fn0();
std::cout<<"call of fn0 successful"<<std::endl;
} catch (...) {
std::cerr<<"OOOPS!!!"<<std::endl;
}
return 0;
}

@ -53,7 +53,8 @@ namespace mrw {
- if any exception is thrown, specify @c throw(mrw::exception)
- if no exception is thrown, specify @c throw(std::bad_exception)
-# document the exact exception thrown with Doxygen's \@throw tag
-# write an unexpected handler as follows:
-# write an unexpected handler as follows
(or link to a @ref AutoTrace "library"):
@code
void unexpectedHandler() {
@ -83,6 +84,9 @@ namespace mrw {
For a proof of concept refer to
@ref exceptionhandling.cpp "the example exceptionhandling.cpp".
The unexpected handler is implemented ready to use in @ref
AutoTrace "a separate library".
*/
//@{
@ -114,12 +118,16 @@ leave fn0
call of fn0 successful
@endverbatim
The unexpected handler is implemented ready to use in @ref
AutoTrace "a separate library".
Please note, that without the exception concept and without the
unexpected handler, the program would abort in function fn2 on
line 25. The output was produced by the following code:
*/
/** @brief replacement for @c std::exception, that collects a stack trace
@pre #include <mrw/exception.hpp>
This exception class behaves exactely like @c std::exception,
but it collects a stack trace in the constructor and offers a

@ -85,26 +85,26 @@ mrw::Exec& mrw::Exec::operator=(const mrw::Exec& e) throw(std::bad_exception) {
mrw::Exec& mrw::Exec::execute(bool throwExc) throw(mrw::exception) {
/** This method calls @c fork, sets up a pipe connection to pass @c
stdot and @c stderr from the child process to the parent process
stdout and @c stderr from the child process to the parent process
using mrw::pipe and calls @c execvp to execute the program. */
_success = false;
_res = _err = "";
mrw::pipe stdout, stderr;
if (!stdout || !stderr)
mrw::pipe stdOut, stdErr;
if (!stdOut || !stdErr)
throw mrw::ExecutionFailedExc("cannot create pipe", *_cmd);
pid_t pid(fork());
if (pid<0)
throw ExecutionFailedExc("cannot fork", *_cmd);
if (pid) { // parent
stdout.close_out();
stderr.close_out();
if (!stdout || !stderr)
stdOut.close_out();
stdErr.close_out();
if (!stdOut || !stdErr)
throw ExecutionFailedExc("cannot close pipe", *_cmd);
int num1(0), num2(0);
for (char buf1[4096], buf2[4096];
(num1=read(stdout.istream(), buf1, sizeof(buf1)))>0 ||
(num1=read(stdOut.istream(), buf1, sizeof(buf1)))>0 ||
num1==-1 && errno==EINTR ||
(num2=read(stderr.istream(), buf2, sizeof(buf2)))>0 ||
(num2=read(stdErr.istream(), buf2, sizeof(buf2)))>0 ||
num2==-1 && errno==EINTR;
_res += std::string(buf1, num1), _err += std::string(buf2, num2));
if (num1==-1 || num2==-1)
@ -120,10 +120,10 @@ mrw::Exec& mrw::Exec::execute(bool throwExc) throw(mrw::exception) {
}
}
} else { // child
stdout.close_in();
stderr.close_in();
stdout.connect_cout();
stderr.connect_cerr();
stdOut.close_in();
stdErr.close_in();
stdOut.connect_cout();
stdErr.connect_cerr();
execvp(_cmd->path(), _cmd->args());
exit(1); // execute failed
}

@ -45,6 +45,7 @@ namespace mrw {
class Cmd;
/** @brief Exception: Execution of command failed.
@pre #include <mrw/exec.hpp>
This exception is thrown, if the exection of a command in
mrw::Exec is failed. That means, it was not possible to fork or
@ -64,10 +65,11 @@ namespace mrw {
};
/** @brief Execute a command in a new process.
@pre #include <mrw/exec.hpp>
This class handles the execution of a command in a new process
and returns the two streams @c cout and @cerr, also known as @c
stderr and @stdout.
and returns the two streams @c cout and @c cerr, also known as @c
stderr and @c stdout.
There are different ways of usage for this class. A simple way,
one line of code, to get only the resulting stream (no error)
@ -188,6 +190,7 @@ namespace mrw {
};
/** @brief A system command to be executed
@pre #include <mrw/exec.hpp>
This class is used in conjunction with mrw::Exec. It mus be
initialized with the command name, then the command parameters

@ -1,26 +1,31 @@
CLEANFILES = doxygen.error
AM_CPPFLAGS = -I..
CLEANFILES = doxygen.error
examplesdir = ${pkgdatadir}/examples
examples_DATA = examples/*
htmldir = ${pkgdatadir}/doc/html
html_DATA = doc/html/*
EXTRA_DIST = test.dat ${examples_DATA} ${html_DATA}
pdfdir = ${pkgdatadir}/doc/pdf
pdf_DATA = doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf
EXTRA_DIST = test.dat ${examples_DATA} ${html_DATA} ${pdf_DATA}
lib_LTLIBRARIES = libmrw.la libmrwexcstderr.la
lib_LTLIBRARIES = libmrw.la libmrwexcstderr.la libmrwexclog4cxx.la
libmrw_la_SOURCES = mrw.hpp \
auto.hpp auto.cpp unistd.hpp \
stacktrace.hpp stacktrace.cpp exception.hpp exception.cpp \
exec.hpp exec.cpp
libmrw_la_LDFLAGS = -version-info @MAJOR@:@MINOR@
libmrw_la_LIBADD = -liberty -lbfd
libmrwexcstderr_la_SOURCES = autostacktracestderr.cpp
libmrwexcstderr_la_LDFLAGS = -version-info @MAJOR@:@MINOR@
libmrwexcstderr_la_LIBADD = -lmrw
check_PROGRAMS = auto_test exec_test stacktrace_test
libmrwexclog4cxx_la_SOURCES = autostacktracelog4cxx.cpp
libmrwexclog4cxx_la_LDFLAGS = -version-info @MAJOR@:@MINOR@
libmrwexclog4cxx_la_LIBADD = -lmrw
check_PROGRAMS = auto_test exec_test stacktrace_test mrwexcstderr_test mrwexclog4cxx_test
auto_test_SOURCES = auto_test.cpp
auto_test_CPPFLAGS = -I.. -g3
auto_test_LDADD = -lmrw -lcppunit
@ -30,8 +35,18 @@ exec_test_LDADD = -lmrw -lcppunit
stacktrace_test_SOURCES = stacktrace_test.cpp
stacktrace_test_CPPFLAGS = -I.. -g3
stacktrace_test_LDADD = -lmrw -lcppunit
mrwexcstderr_test_SOURCES = mrwexcstderr_test.cpp
mrwexcstderr_test_CPPFLAGS = -I.. -g3
mrwexcstderr_test_LDADD = -lmrwexcstderr -lcppunit
mrwexclog4cxx_test_SOURCES = mrwexclog4cxx_test.cpp
mrwexclog4cxx_test_CPPFLAGS = -I.. -g3
mrwexclog4cxx_test_LDADD = -lmrwexclog4cxx -lcppunit -llog4cxx
TESTS = ${check_PROGRAMS}
doc: doc/html/index.html
doc/html/index.html: doxyfile *.[ch]pp
deps = ../COPYING ../README ../INSTALL ../NEWS ../ChangeLog
doc: doc/html/index.html doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf
doc/html/index.html: doxyfile *.[ch]pp ${deps}
doxygen doxyfile
doc/latex/@PACKAGENAME@-@MAJOR@.@MINOR@.pdf: doxyfile *.[ch]pp ${deps}
cd doc/latex && make && \
mv refman.pdf @PACKAGENAME@-@MAJOR@.@MINOR@.pdf

@ -1,50 +1,52 @@
/** @mainpage
@section license License and Copyright
- All files are under GNU LGPL license.
- All files are copyrighted by Marc Wäckerlin.
- There is no warranty.
- For details, read the file LICENSE in your distribution.
@section intro Introduction
This library cares a about:
- resource management
- execution of UNIX sub processes
- stack trace
- exception handling
For details, see the modules page.
@section link Compile and Link Options
@verbinclude README
To be able to get the source file name&nbsp;/ line number
information in stack trace, you need the debug information compile
option @c -g. For compilation on Solaris, you may need the option
@c -D__solaris__. You must link to the MRW C++ Library. For this
you need the link option @c -lmrw.
For details, see the <a href="modules.html">"Modules"</a> page.
@section download Download and Installation
@section download Download
Download this version from here:
- Source TAR-Ball (<code>./configure && make all install</code>):
- http://marc.waeckerlin.org/mrw-c++/mrw-c++-@MAJOR@.@MINOR@.tar.gz
- RPM Packages (built on i586/SuSE):
- http://marc.waeckerlin.org/mrw-c++/mrw-c++-@MAJOR@.@MINOR@-1.i586.rpm
- http://marc.waeckerlin.org/mrw-c++/mrw-c++-devel-@MAJOR@.@MINOR@-1.i586.rpm
Not yet available:
- http://marc.waeckerlin.org/mrw-c++/mrw-c++-@MAJOR@.@MINOR@.rpm
- http://marc.waeckerlin.org/mrw-c++/mrw-c++-devel-@MAJOR@.@MINOR@.rpm
Download this documentation in PDF:
- http://marc.waeckerlin.org/mrw-c++/mrw-c++-@MAJOR@.@MINOR@.pdf
The homepage is on:
- http://marc.waeckerlin.org/mrw-c++/index.html
Install it with:
@section usage Usage of the Library
Include the headers you need with prefix @c mrw, e.g.:
@verbatim
#include <mrw/stacktrace.hpp>
@endverbatim
Compile with debug information enabled, thats option @c -g and
link to the library with option @c -lmrw, e.g.;
@verbatim
tar xzvf mrw-c++-@MAJOR@.@MINOR@.tar.gz
cd mrw-c++-@MAJOR@.@MINOR@
./configure
make all check install
g++ -g -o myprogram myprogram.cpp -lmrw
@endverbatim
For the @ref AutoTools "unexpected handler" you need to link with
@c -lmrwexcstderr or @c -lmrwexclog4cxx.
@section moreinfo Additional Information
See the <a href="pages.html">"Related Pages"</a>.
- @ref license "License Information (LGPL)"
- @ref install "Compilation and Installation Information"
- @ref news "Breaking News"
- @ref changes "Change Log"
*/
/** @page license License
@ -53,6 +55,9 @@
/** @page readme Readme
@verbinclude README */
/** @page install Installation
@verbinclude INSTALL */
/** @page news News
@verbinclude NEWS */

@ -0,0 +1,68 @@
#include <mrw/exception.hpp>
#include <log4cxx/basicconfigurator.h>
#include <cppunit/TestFixture.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
namespace mrw {
class AutoExcLog4CxxTest: public CppUnit::TestFixture {
private:
bool enter_unexpectedThrow;
bool exit_unexpectedThrow;
bool enter_passUnexpected;
bool exit_passUnexpected;
bool enter_catchUnexpected;
bool exit_catchUnexpected;
public:
void setUp() {
enter_unexpectedThrow = false;
exit_unexpectedThrow = false;
enter_passUnexpected = false;
exit_passUnexpected = false;
enter_catchUnexpected = false;
exit_catchUnexpected = false;
}
void unexpectedThrow() throw(std::bad_exception) {
enter_unexpectedThrow = true;
throw mrw::exception();
exit_unexpectedThrow = true;
}
void passUnexpected() throw(std::bad_exception) {
enter_passUnexpected = true;
unexpectedThrow();
exit_passUnexpected = true;
}
void catchUnexpected() throw() {
enter_catchUnexpected = true;
bool caught(false);
try {
passUnexpected();
} catch (std::bad_exception&) {
caught = true;
}
CPPUNIT_ASSERT(caught);
exit_catchUnexpected = true;
}
void testcase() {
catchUnexpected();
CPPUNIT_ASSERT(enter_catchUnexpected &&
enter_passUnexpected &&
enter_unexpectedThrow &&
exit_catchUnexpected &&
!exit_passUnexpected &&
!exit_unexpectedThrow);
}
CPPUNIT_TEST_SUITE(AutoExcLog4CxxTest);
CPPUNIT_TEST(testcase);
CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(AutoExcLog4CxxTest);
}
int main() {
log4cxx::BasicConfigurator::configure();
CppUnit::TextUi::TestRunner runner;
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
return runner.run() ? 0 : 1;
}

@ -0,0 +1,66 @@
#include <mrw/exception.hpp>
#include <cppunit/TestFixture.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
namespace mrw {
class AutoExcStderrTest: public CppUnit::TestFixture {
private:
bool enter_unexpectedThrow;
bool exit_unexpectedThrow;
bool enter_passUnexpected;
bool exit_passUnexpected;
bool enter_catchUnexpected;
bool exit_catchUnexpected;
public:
void setUp() {
enter_unexpectedThrow = false;
exit_unexpectedThrow = false;
enter_passUnexpected = false;
exit_passUnexpected = false;
enter_catchUnexpected = false;
exit_catchUnexpected = false;
}
void unexpectedThrow() throw(std::bad_exception) {
enter_unexpectedThrow = true;
throw mrw::exception();
exit_unexpectedThrow = true;
}
void passUnexpected() throw(std::bad_exception) {
enter_passUnexpected = true;
unexpectedThrow();
exit_passUnexpected = true;
}
void catchUnexpected() throw() {
enter_catchUnexpected = true;
bool caught(false);
try {
passUnexpected();
} catch (std::bad_exception&) {
caught = true;
}
CPPUNIT_ASSERT(caught);
exit_catchUnexpected = true;
}
void testcase() {
catchUnexpected();
CPPUNIT_ASSERT(enter_catchUnexpected &&
enter_passUnexpected &&
enter_unexpectedThrow &&
exit_catchUnexpected &&
!exit_passUnexpected &&
!exit_unexpectedThrow);
}
CPPUNIT_TEST_SUITE(AutoExcStderrTest);
CPPUNIT_TEST(testcase);
CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(AutoExcStderrTest);
}
int main() {
CppUnit::TextUi::TestRunner runner;
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
return runner.run() ? 0 : 1;
}

@ -53,10 +53,48 @@ namespace mrw {
- a system with ELF binaries (LINUX, Solaris, ...)
- debug information, compile option @c -g
- it must be linked with @c -libery and @c -lbfd
@subsection sttech Technology
On GNU glibc based systems (Linux), the stack trace is collected
with GNU glibc's function @c backtrace(). On other systems
(Solaris) it is collected using the GNU gcc's internal function @c
__builtin_return_address(). With both functions, at most 50 steps
back are collected.
The evaluation is not done with the glibc library function @c
backtrace_symbols(), because this function is unable to print
the source file name and line number information. Instead of
this, the executable binary is loaded into the memory and
evaluated using the bdf library functions. For this the stack
tracer needs to know how to find out which executable is
running. It is possible to get this information automatically on
Linux and Solaris. On other systems, I don't have this
information, but you can either tell me, and I integrate support
for your system (when I have time to do it), or provide the
executable file name as an argument to @c
mrw::StackTrace::createSymtable().
@subsection stdrawbacks Draw Backs
Unfortunately it is not possible to extract the source file name
and line number information if the executable was not compiled
with debug option @c -g. But what's worse, it is not possible to
ger symbolic information from libraries linked to the
executable. Perhaps it could be possible, if I'd add a
possibility to read and evaluate these libraries, but that's for
a future release.
@todo Add support to read debugging information from libraries
that are linked to the executable.
@todo Add support for alternative symbol evaluation using @c
backtrace_symbols.
*/
//@{
/** @brief store and print a stack trace of the actual position in code
@pre #include <mrw/stacktrace.hpp>
In the constructor, a stack trace is stored, but not yet
evaluated. Therefore storing a stack trace is relatively

@ -8,8 +8,10 @@ namespace mrw {
/** @addtogroup AutoTools */
//@{
/// class that implements an unnamed UNIX pipe
/** Implements a UNIX pipe that is automatically closed in
/** @brief class that implements an unnamed UNIX pipe
@pre #include <mrw/unistd.hpp>
Implements a UNIX pipe that is automatically closed in
destructor and offers some facilities. */
class pipe {
private:

Loading…
Cancel
Save