From 0adaab0ad9ad5df36da89413f3bed03a9f7cfa4b Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Tue, 6 Jul 2010 09:07:15 +0200 Subject: [PATCH] plug leak --- src/core/fatal-impl.cc | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/core/fatal-impl.cc b/src/core/fatal-impl.cc index 0d16bb692..9ee654a57 100644 --- a/src/core/fatal-impl.cc +++ b/src/core/fatal-impl.cc @@ -30,6 +30,19 @@ namespace ns3 { namespace FatalImpl { +/** + * Note on implementation: the singleton pattern we use here is tricky because + * it has to deal with: + * - make sure that whoever calls Register (potentially before main enters and + * before any constructor run in this file) succeeds + * - make sure that whoever calls Unregister (potentially before FlushStream runs + * but also after it runs) succeeds + * - make sure that the memory allocated with new is deallocated with delete before + * the program exits so that valgrind reports no leaks + * + * This is why we go through all the painful hoops below. + */ + /* File-scope */ namespace { std::list **PeekStreamList (void) @@ -66,7 +79,17 @@ RegisterStream (std::ostream* stream) void UnregisterStream (std::ostream* stream) { - GetStreamList ()->remove (stream); + std::list **pl = PeekStreamList (); + if (*pl == 0) + { + return; + } + (*pl)->remove (stream); + if ((*pl)->empty ()) + { + delete *pl; + *pl = 0; + } } @@ -83,16 +106,22 @@ namespace { void FlushStreams (void) { - struct sigaction hdl; + std::list **pl = PeekStreamList (); + if (pl == 0) + { + return; + } + /* Override default SIGSEGV handler - will flush subsequent * streams even if one of the stream pointers is bad. * The SIGSEGV override should only be active for the * duration of this function. */ + struct sigaction hdl; hdl.sa_handler=sigHandler; sigaction (SIGSEGV, &hdl, 0); - std::list *l = GetStreamList (); + std::list *l = *pl; /* Need to do it this way in case any of the ostream* causes SIGSEGV */ while (!l->empty ()) @@ -113,6 +142,9 @@ FlushStreams (void) std::cout.flush (); std::cerr.flush (); std::clog.flush (); + + delete l; + *pl = 0; } } //FatalImpl