A Discrete-Event Network Simulator
API
fatal-impl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 NICTA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Quincy Tse <quincy.tse@nicta.com.au>
18  */
19 #include "fatal-impl.h"
20 
21 #include "log.h"
22 
23 #include <csignal>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <iostream>
27 #include <list>
28 
29 #ifdef __WIN32__
30 struct sigaction
31 {
32  void (*sa_handler)(int);
33  int sa_flags;
34  int sa_mask;
35 };
36 
37 int
38 sigaction(int sig, struct sigaction* action, struct sigaction* old)
39 {
40  if (sig == -1)
41  {
42  return 0;
43  }
44  if (old == nullptr)
45  {
46  if (signal(sig, SIG_DFL) == SIG_ERR)
47  {
48  return -1;
49  }
50  }
51  else
52  {
53  if (signal(sig, action->sa_handler) == SIG_ERR)
54  {
55  return -1;
56  }
57  }
58  return 0;
59 }
60 #endif
61 
84 namespace ns3
85 {
86 
87 NS_LOG_COMPONENT_DEFINE("FatalImpl");
88 
89 namespace FatalImpl
90 {
91 
97 namespace
98 {
99 
107 std::list<std::ostream*>**
109 {
111  static std::list<std::ostream*>* streams = nullptr;
112  return &streams;
113 }
114 
121 std::list<std::ostream*>*
123 {
125  std::list<std::ostream*>** pstreams = PeekStreamList();
126  if (*pstreams == nullptr)
127  {
128  *pstreams = new std::list<std::ostream*>();
129  }
130  return *pstreams;
131 }
132 
133 } // unnamed namespace
134 
135 void
136 RegisterStream(std::ostream* stream)
137 {
138  NS_LOG_FUNCTION(stream);
139  GetStreamList()->push_back(stream);
140 }
141 
142 void
143 UnregisterStream(std::ostream* stream)
144 {
145  NS_LOG_FUNCTION(stream);
146  std::list<std::ostream*>** pl = PeekStreamList();
147  if (*pl == nullptr)
148  {
149  return;
150  }
151  (*pl)->remove(stream);
152  if ((*pl)->empty())
153  {
154  delete *pl;
155  *pl = nullptr;
156  }
157 }
158 
165 namespace
166 {
167 
177 void
178 sigHandler(int sig)
179 {
180  NS_LOG_FUNCTION(sig);
181  FlushStreams();
182  std::abort();
183 }
184 } // unnamed namespace
185 
186 void
188 {
190  std::list<std::ostream*>** pl = PeekStreamList();
191  if (*pl == nullptr)
192  {
193  return;
194  }
195 
196  /* Override default SIGSEGV handler - will flush subsequent
197  * streams even if one of the stream pointers is bad.
198  * The SIGSEGV override should only be active for the
199  * duration of this function. */
200  struct sigaction hdl;
201  hdl.sa_handler = sigHandler;
202  sigaction(SIGSEGV, &hdl, nullptr);
203 
204  std::list<std::ostream*>* l = *pl;
205 
206  /* Need to do it this way in case any of the ostream* causes SIGSEGV */
207  while (!l->empty())
208  {
209  std::ostream* s(l->front());
210  l->pop_front();
211  s->flush();
212  }
213 
214  /* Restore default SIGSEGV handler (Not that it matters anyway) */
215  hdl.sa_handler = SIG_DFL;
216  sigaction(SIGSEGV, &hdl, nullptr);
217 
218  /* Flush all opened FILE* */
219  std::fflush(nullptr);
220 
221  /* Flush stdandard streams - shouldn't be required (except for clog) */
222  std::cout.flush();
223  std::cerr.flush();
224  std::clog.flush();
225 
226  delete l;
227  *pl = nullptr;
228 }
229 
230 } // namespace FatalImpl
231 
232 } // namespace ns3
ns3::FatalImpl::RegisterStream(), ns3::FatalImpl::UnregisterStream(), and ns3::FatalImpl::FlushStream...
void UnregisterStream(std::ostream *stream)
Unregister a stream for flushing on abnormal exit.
Definition: fatal-impl.cc:143
void sigHandler(int sig)
Overrides normal SIGSEGV handler once the HandleTerminate function is run.
Definition: fatal-impl.cc:178
std::list< std::ostream * > ** PeekStreamList()
Static variable pointing to the list of output streams to be flushed on fatal errors.
Definition: fatal-impl.cc:108
std::list< std::ostream * > * GetStreamList()
Get the stream list, initializing it if necessary.
Definition: fatal-impl.cc:122
void RegisterStream(std::ostream *stream)
Register a stream to be flushed on abnormal exit.
Definition: fatal-impl.cc:136
void FlushStreams()
Flush all currently registered streams.
Definition: fatal-impl.cc:187
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.