A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
fatal-impl.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 NICTA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Quincy Tse <quincy.tse@nicta.com.au>
19  */
20 #include "fatal-impl.h"
21 
22 #include <iostream>
23 #include <list>
24 
25 #include <cstdlib>
26 #include <cstdio>
27 
28 #include <csignal>
29 
30 namespace ns3 {
31 namespace FatalImpl {
32 
46 /* File-scope */
47 namespace {
48 std::list<std::ostream*> **PeekStreamList (void)
49 {
50  static std::list<std::ostream*> *streams = 0;
51  return &streams;
52 }
53 std::list<std::ostream*> *GetStreamList (void)
54 {
55  std::list<std::ostream*> **pstreams = PeekStreamList ();
56  if (*pstreams == 0)
57  {
58  *pstreams = new std::list<std::ostream*> ();
59  }
60  return *pstreams;
61 }
62 struct destructor
63 {
65  {
66  std::list<std::ostream*> **pstreams = PeekStreamList ();
67  delete *pstreams;
68  *pstreams = 0;
69  }
70 };
71 }
72 
73 void
74 RegisterStream (std::ostream* stream)
75 {
76  GetStreamList ()->push_back (stream);
77 }
78 
79 void
80 UnregisterStream (std::ostream* stream)
81 {
82  std::list<std::ostream*> **pl = PeekStreamList ();
83  if (*pl == 0)
84  {
85  return;
86  }
87  (*pl)->remove (stream);
88  if ((*pl)->empty ())
89  {
90  delete *pl;
91  *pl = 0;
92  }
93 }
94 
95 
96 namespace {
97 /* Overrides normal SIGSEGV handler once the
98  * HandleTerminate function is run. */
99 void sigHandler (int sig)
100 {
101  FlushStreams ();
102  std::abort ();
103 }
104 }
105 
106 void
108 {
109  std::list<std::ostream*> **pl = PeekStreamList ();
110  if (*pl == 0)
111  {
112  return;
113  }
114 
115 
116  /* Override default SIGSEGV handler - will flush subsequent
117  * streams even if one of the stream pointers is bad.
118  * The SIGSEGV override should only be active for the
119  * duration of this function. */
120  struct sigaction hdl;
121  hdl.sa_handler=sigHandler;
122  sigaction (SIGSEGV, &hdl, 0);
123 
124  std::list<std::ostream*> *l = *pl;
125 
126  /* Need to do it this way in case any of the ostream* causes SIGSEGV */
127  while (!l->empty ())
128  {
129  std::ostream* s (l->front ());
130  l->pop_front ();
131  s->flush ();
132  }
133 
134  /* Restore default SIGSEGV handler (Not that it matters anyway) */
135  hdl.sa_handler=SIG_DFL;
136  sigaction (SIGSEGV, &hdl, 0);
137 
138  /* Flush all opened FILE* */
139  std::fflush (0);
140 
141  /* Flush stdandard streams - shouldn't be required (except for clog) */
142  std::cout.flush ();
143  std::cerr.flush ();
144  std::clog.flush ();
145 
146  delete l;
147  *pl = 0;
148 }
149 
150 } //FatalImpl
151 } //ns3