diff -r b08fe828b686 src/core/abort.h --- a/src/core/abort.h Wed Jun 02 11:14:06 2010 -0400 +++ b/src/core/abort.h Thu Jun 03 13:44:59 2010 +1000 @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2008 INRIA + * Copyright (c) 2008 INRIA, 2010 NICTA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,50 +15,120 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * Author: Original author unknown + * Quincy Tse */ #ifndef NS3_ABORT_H #define NS3_ABORT_H #include "fatal-error.h" +/** + * \ingroup debugging + * \brief Abnormal program termination + * + * \param msg message to output when this macro is hit. + * + * This macro is essentially equivalent to NS_FATAL_ERROR, + * excepts it prepends the error message with the string + * "aborted. ". When this macro is hit a runtime, the + * program will be halted using std::terminate, which + * triggers clean up code regestered by std::set_terminate. + * + * This macro is enable unconditionally in all builds, + * including debug and optimized builds. + * + * \see NS_FATAL_ERROR + */ #define NS_ABORT_MSG(msg) \ - do { \ - std::cerr << "file=" << __FILE__ << \ - ", line=" << __LINE__ << ", abort, msg=\"" << \ - msg << "\"" << std::endl; \ - int *a = 0; \ - *a = 0; \ + do { \ + std::cerr << "aborted. "; \ + NS_FATAL_ERROR (msg); \ } while (false) -#define NS_ABORT_IF(cond) \ - do { \ - if (cond) \ - { \ - std::cerr << "file=" << __FILE__ << \ - ", line=" << __LINE__ << ", abort on=\""#cond << \ - "\"" << std::endl; \ - int *a = 0; \ - *a = 0; \ - } \ +/** + * \ingroup debugging + * \brief Abnormal program termination if cond is true. + * + * \param cond condition to be evaluated. + * + * This is similar to NS_ASSERT(!(cond)), except this check + * is enabled in all builds. If cond is evaluated to true, + * the espression evaluating to true is printed to stderr, + * followed by a call to the NS_FATAL_ERROR_NO_MSG() macro + * which prints the details of filename and line number to + * stderr. The program will be halted by calling + * std::terminate(), triggering any clean up code registered + * by std::set_terminate (NS3 default is a stream-flushing + * code, but may be overridden). + * + * This macro is enable unconditionally in all builds, + * including debug and optimized builds. + */ +#define NS_ABORT_IF(cond) \ + do { \ + if (cond) \ + { \ + std::cerr << "aborted. cond=\"" << #cond << ", "; \ + NS_FATAL_ERROR_NO_MSG (); \ + } \ } while (false) -#define NS_ABORT_MSG_IF(cond, msg) \ - do { \ - if (cond) \ - { \ - std::cerr << "file=" << __FILE__ << \ - ", line=" << __LINE__ << ", abort on=\""#cond << \ - "\", msg=\"" << msg << "\"" << std::endl; \ - int *a = 0; \ - *a = 0; \ - } \ +/** + * \ingroup debugging + * \brief Abnormal program termination if cond is true. + * + * \param cond condition to be evaluated. + * \param msg message to output when cond is true. + * + * This is similar to NS_ASSERT_MSG(!(cond)), except this + * check is enabled in all builds. If cond is evaluated to + * true, the espression evaluating to true is printed to + * stderr, followed by a call to the NS_FATAL_ERROR() macro + * which prints the user-specified error message, and details + * of filename and line number to stderr. The program will + * be halted by calling std::terminate(), triggering any + * clean up code registered by std::set_terminate (NS3 + * default is a stream-flushing code, but may be overridden). + * + * This macro is enable unconditionally in all builds, + * including debug and optimized builds. + */ +#define NS_ABORT_MSG_IF(cond, msg) \ + do { \ + if (cond) \ + { \ + std::cerr << "aborted. cond=\"" << #cond << "\", "; \ + NS_FATAL_ERROR (msg); \ + } \ } while (false) -#define NS_ABORT_UNLESS(cond) \ +/** + * \ingroup debugging + * \brief Abnormal program termination if cond is false. + * + * \param cond condition to be evaluated. + * + * This is an alias for NS_ABORT_IF(!(cond)) + * + * \see NS_ABORT_IF + */ +#define NS_ABORT_UNLESS(cond) \ NS_ABORT_IF(!(cond)) -#define NS_ABORT_MSG_UNLESS(cond, msg) \ +/** + * \ingroup debugging + * \brief Abnormal program termination if cond is false. + * + * \param cond condition to be evaluated. + * \param msg message to output if cond is false. + * + * This is an alias for NS_ABORT_MSG_IF(!(cond)) + * + * \see NS_ABORT_MSG_IF + */ +#define NS_ABORT_MSG_UNLESS(cond, msg) \ NS_ABORT_MSG_IF(!(cond),msg) #endif /* NS3_ABORT_H */ diff -r b08fe828b686 src/core/assert.h --- a/src/core/assert.h Wed Jun 02 11:14:06 2010 -0400 +++ b/src/core/assert.h Thu Jun 03 13:44:59 2010 +1000 @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2006 INRIA + * Copyright (c) 2006 INRIA, 2010 NICTA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,14 +16,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * Quincy Tse */ -#ifndef ASSERT_H -#define ASSERT_H +#ifndef NS_ASSERT_H +#define NS_ASSERT_H #ifdef NS3_ASSERT_ENABLE #include +#include "fatal-error.h" + /** * \ingroup core * \defgroup debugging Debugging @@ -39,6 +42,15 @@ * not true, the program halts. These checks are built * into the program only in debugging builds. They are * removed in optimized builds. + * + * These macro are intended to check certain conditions + * to be true. Do not put code that also have side effects + * that your program relies on (eg. code that advances + * an iterator and return false at end of file) because + * the code will not be executed on release builds!! + * + * If assertion-style checks are required for release + * builds, use NS_ABORT_UNLESS and NS_ABORT_MSG_UNLESS. */ /** @@ -47,18 +59,16 @@ * * At runtime, in debugging builds, if this condition is not * true, the program prints the source file, line number and - * unverified condition and halts by dereferencing a null pointer. + * unverified condition and halts by calling std::terminate */ #define NS_ASSERT(condition) \ do \ { \ if (!(condition)) \ { \ - std::cerr << "assert failed. file=" << __FILE__ << \ - ", line=" << __LINE__ << ", cond=\""#condition << \ - "\"" << std::endl; \ - int *a = 0; \ - *a = 0; \ + std::cerr << "assert failed. cond=\"" << \ + #condition << "\", "; \ + NS_FATAL_ERROR_NO_MSG(); \ } \ } \ while (false) @@ -71,18 +81,18 @@ * * At runtime, in debugging builds, if this condition is not * true, the program prints the message to output and - * halts by dereferencing a null pointer. + * halts by calling std::terminate. */ -#define NS_ASSERT_MSG(condition, message) \ - do \ - { \ - if (!(condition)) \ - { \ - std::cerr << message << std::endl; \ - int *a = 0; \ - *a = 0; \ - } \ - } \ +#define NS_ASSERT_MSG(condition, message) \ + do \ + { \ + if (!(condition)) \ + { \ + std::cerr << "assert failed. cond=\"" << \ + #condition << "\", "; \ + NS_FATAL_ERROR (message); \ + } \ + } \ while (false) #else /* NS3_ASSERT_ENABLE */ diff -r b08fe828b686 src/core/fatal-error.h --- a/src/core/fatal-error.h Wed Jun 02 11:14:06 2010 -0400 +++ b/src/core/fatal-error.h Thu Jun 03 13:44:59 2010 +1000 @@ -1,6 +1,6 @@ /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2006 INRIA + * Copyright (c) 2006 INRIA, 2010 NICTA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,11 +16,39 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * Quincy Tse */ -#ifndef FATAL_ERROR_H -#define FATAL_ERROR_H +#ifndef NS3_FATAL_ERROR_H +#define NS3_FATAL_ERROR_H #include +#include +#include + +#include "fatal-impl.h" + +/** + * \ingroup debugging + * \brief fatal error handling + * + * When this macro is hit at runtime, details of filename + * and line number is printed to stderr, and the program + * is halted by calling std::terminate(). This will + * trigger any clean up code registered by + * std::set_terminate (NS3 default is a stream-flushing + * code), but may be overridden. + * + * This macro is enabled unconditionally in all builds, + * including debug and optimized builds. + */ +#define NS_FATAL_ERROR_NO_MSG() \ + do \ + { \ + std::cerr << "file=" << __FILE__ << ", line=" << \ + __LINE__ << std::endl; \ + std::terminate (); \ + } \ + while (false) /** * \ingroup debugging @@ -28,20 +56,66 @@ * * \param msg message to output when this macro is hit. * - * When this macro is hit at runtime, the user-specified - * error message is output and the program is halted by - * dereferencing a null pointer. This macro is enabled - * unconditionally in all builds, including debug and - * optimized builds. + * When this macro is hit at runtime, the user-specified + * error message is printed to stderr, followed by a call + * to the NS_FATAL_ERROR_NO_MSG() macro which prints the + * details of filename and line number to stderr. The + * program will be halted by calling std::terminate(), + * triggering any clean up code registered by + * std::set_terminate (NS3 default is a stream-flushing + * code, but may be overridden). + * + * This macro is enabled unconditionally in all builds, + * including debug and optimized builds. */ -#define NS_FATAL_ERROR(msg) \ +#define NS_FATAL_ERROR(msg) \ do \ { \ - std::cerr << msg << std::endl; \ - int *a = 0; \ - *a = 0; \ + std::cerr << "msg=\"" << msg << "\", "; \ + NS_FATAL_ERROR_NO_MSG(); \ } \ while (false) +#define NS_FATAL_SET_CXX_VERBOSE() \ + do \ + { \ + std::set_terminate (__gnu_cxx::__verbose_terminate_handler); \ + } \ + while (false) + +#define NS_FATAL_SET_CXX_SILENT() \ + do \ + { \ + std::set_terminate (std::abort); \ + } \ + while (false) + +#define NS_FATAL_SET_DEFAULT() \ + do \ + { \ + std::set_terminate (ns3::_handleTerminate); \ + } \ + while (false) + +#define NS_FATAL_SET_HANDLER(handler) \ + do \ + { \ + std::set_terminate (static_cast(handler)); \ + } \ + while (false) + +#define NS_FATAL_REGISTER_STREAM(stream) \ + do \ + { \ + ns3::_registerStream (stream); \ + } \ + while (false) + +#define NS_FATAL_UNREGISTER_STREAM(stream) \ + do \ + { \ + ns3::_unregisterStream (stream); \ + } \ + while (false) #endif /* FATAL_ERROR_H */ diff -r b08fe828b686 src/core/fatal-impl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/fatal-impl.cc Thu Jun 03 13:44:59 2010 +1000 @@ -0,0 +1,66 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 NICTA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Quincy Tse + */ +#include "fatal-impl.h" + +#include +#include + +#include +#include + +using std::list; +using std::ostream; + +namespace ns3 { + +/* File-scope */ +namespace { + list s_streams; +} + +void +_registerStream (ostream& stream) +{ + s_streams.push_back (&stream); +} + +void +_unregisterStream (ostream& stream) +{ + s_streams.remove (&stream); +} + +void +_handleTerminate (void) +{ + for (list::iterator it = s_streams.begin (); + it != s_streams.end (); ++it) + { + (*it)->flush (); + } + + std::fflush (0); + + std::cout.flush (); + std::cerr.flush (); + std::abort (); +} + +} diff -r b08fe828b686 src/core/fatal-impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core/fatal-impl.h Thu Jun 03 13:44:59 2010 +1000 @@ -0,0 +1,36 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 NICTA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Quincy Tse + */ + +#ifndef FATAL_IMPL_H +#define FATAL_IMPL_H + +#include + +namespace ns3 { + +void _registerStream (std::ostream& stream); + +void _unregisterStream (std::ostream& stream); + +void _handleTerminate (void); + +} + +#endif diff -r b08fe828b686 src/core/wscript --- a/src/core/wscript Wed Jun 02 11:14:06 2010 -0400 +++ b/src/core/wscript Thu Jun 03 13:44:59 2010 +1000 @@ -80,6 +80,7 @@ 'type-traits-test-suite.cc', 'traced-callback-test-suite.cc', 'ptr-test-suite.cc', + 'fatal-impl.cc', ] headers = bld.new_task_gen('ns3header')