A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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__
30struct sigaction
31{
32 void (*sa_handler)(int);
33 int sa_flags;
34 int sa_mask;
35};
36
37int
38sigaction(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
62/**
63 * \file
64 * \ingroup fatalimpl
65 * \brief ns3::FatalImpl::RegisterStream(), ns3::FatalImpl::UnregisterStream(),
66 * and ns3::FatalImpl::FlushStreams() implementations;
67 * see Implementation note!
68 *
69 * \note Implementation.
70 *
71 * The singleton pattern we use here is tricky because we have to ensure:
72 *
73 * - RegisterStream() succeeds, even if called before \c main() enters and
74 * before any constructor run in this file.
75 *
76 * - UnregisterStream() succeeds, whether or not FlushStreams() has
77 * been called.
78 *
79 * - All memory allocated with \c new is deleted properly before program exit.
80 *
81 * This is why we go through all the painful hoops below.
82 */
83
84namespace ns3
85{
86
87NS_LOG_COMPONENT_DEFINE("FatalImpl");
88
89namespace FatalImpl
90{
91
92/**
93 * \ingroup fatalimpl
94 * Unnamed namespace for fatal streams memory implementation
95 * and signal handler.
96 */
97namespace
98{
99
100/**
101 * \ingroup fatalimpl
102 * \brief Static variable pointing to the list of output streams
103 * to be flushed on fatal errors.
104 *
105 * \returns The address of the static pointer.
106 */
107std::list<std::ostream*>**
109{
111 static std::list<std::ostream*>* streams = nullptr;
112 return &streams;
113}
114
115/**
116 * \ingroup fatalimpl
117 * \brief Get the stream list, initializing it if necessary.
118 *
119 * \returns The stream list.
120 */
121std::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
135void
136RegisterStream(std::ostream* stream)
137{
138 NS_LOG_FUNCTION(stream);
139 GetStreamList()->push_back(stream);
140}
141
142void
143UnregisterStream(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
159/**
160 * \ingroup fatalimpl
161 * Unnamed namespace for fatal streams signal handler.
162 *
163 * This is private to the fatal implementation.
164 */
165namespace
166{
167
168/**
169 * \ingroup fatalimpl
170 * \brief Overrides normal SIGSEGV handler once the HandleTerminate
171 * function is run.
172 *
173 * This is private to the fatal implementation.
174 *
175 * \param [in] sig The signal condition.
176 */
177void
179{
180 NS_LOG_FUNCTION(sig);
181 FlushStreams();
182 std::abort();
183}
184} // unnamed namespace
185
186void
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
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
void sigHandler(int sig)
Overrides normal SIGSEGV handler once the HandleTerminate function is run.
Definition: fatal-impl.cc:178
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.