1 // Copyright 2010 Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "utils/sanity.hpp"
31 #if defined(HAVE_CONFIG_H)
45 #include "utils/format/macros.hpp"
46 #include "utils/logging/macros.hpp"
52 /// List of fatal signals to be intercepted by the sanity code.
54 /// The tests hardcode this list; update them whenever the list gets updated.
55 static int fatal_signals
[] = { SIGABRT
, SIGBUS
, SIGSEGV
, 0 };
58 /// The path to the log file to report on crashes. Be aware that this is empty
59 /// until install_crash_handlers() is called.
60 static std::string logfile
;
63 /// Prints a message to stderr.
65 /// Note that this runs from a signal handler. Calling write() is OK.
67 /// \param message The message to print.
69 err_write(const std::string
& message
)
71 if (::write(STDERR_FILENO
, message
.c_str(), message
.length()) == -1) {
72 // We are crashing. If ::write fails, there is not much we could do,
73 // specially considering that we are running within a signal handler.
74 // Just ignore the error.
79 /// The crash handler for fatal signals.
81 /// The sole purpose of this is to print some informational data before
82 /// reraising the original signal.
84 /// \param signo The received signal.
86 crash_handler(const int signo
)
88 PRE(!logfile
.empty());
90 err_write(F("*** Fatal signal %s received\n") % signo
);
91 err_write(F("*** Log file is %s\n") % logfile
);
92 err_write(F("*** Please report this problem to %s detailing what you were "
93 "doing before the crash happened; if possible, include the log "
94 "file mentioned above\n") % PACKAGE_BUGREPORT
);
96 /// The handler is installed with SA_RESETHAND, so this is safe to do. We
97 /// really want to call the default handler to generate any possible core
99 ::kill(::getpid(), signo
);
103 /// Installs a handler for a fatal signal representing a crash.
105 /// When the specified signal is captured, the crash_handler() will be called to
106 /// print some informational details to the user and, later, the signal will be
107 /// redelivered using the default handler to obtain a core dump.
109 /// \param signo The fatal signal for which to install a handler.
111 install_one_crash_handler(const int signo
)
113 struct ::sigaction sa
;
114 sa
.sa_handler
= crash_handler
;
115 sigemptyset(&sa
.sa_mask
);
116 sa
.sa_flags
= SA_RESETHAND
;
118 if (::sigaction(signo
, &sa
, NULL
) == -1) {
119 const int original_errno
= errno
;
120 LW(F("Could not install crash handler for signal %s: %s") %
121 signo
% std::strerror(original_errno
));
123 LD(F("Installed crash handler for signal %s") % signo
);
127 /// Returns a textual representation of an assertion type.
129 /// The textual representation is user facing.
131 /// \param type The type of the assertion. If the type is unknown for whatever
132 /// reason, a special message is returned. The code cannot abort in such a
133 /// case because this code is dealing for assertion errors.
135 /// \return A textual description of the assertion type.
137 format_type(const utils::assert_type type
)
140 case utils::invariant
: return "Invariant check failed";
141 case utils::postcondition
: return "Postcondition check failed";
142 case utils::precondition
: return "Precondition check failed";
143 case utils::unreachable
: return "Unreachable point reached";
144 default: return "UNKNOWN ASSERTION TYPE";
149 } // anonymous namespace
152 /// Raises an assertion error.
154 /// This function prints information about the assertion failure and terminates
155 /// execution immediately by calling std::abort(). This ensures a coredump so
156 /// that the failure can be analyzed later.
158 /// \param type The assertion type; this influences the printed message.
159 /// \param file The file in which the assertion failed.
160 /// \param line The line in which the assertion failed.
161 /// \param message The failure message associated to the condition.
163 utils::sanity_failure(const assert_type type
, const char* file
,
164 const size_t line
, const std::string
& message
)
166 std::cerr
<< "*** " << file
<< ":" << line
<< ": " << format_type(type
);
167 if (!message
.empty())
168 std::cerr
<< ": " << message
<< "\n";
175 /// Installs persistent handlers for crash signals.
177 /// Should be called at the very beginning of the execution of the program to
178 /// ensure that a signal handler for fatal crash signals is installed.
180 /// \pre The function has not been called before.
182 /// \param logfile_ The path to the log file to report during a crash.
184 utils::install_crash_handlers(const std::string
& logfile_
)
186 #if !defined(NDEBUG) && defined(__minix)
187 static bool installed
= false;
188 #endif /* !defined(NDEBUG) && defined(__minix) */
192 for (const int* iter
= &fatal_signals
[0]; *iter
!= 0; iter
++)
193 install_one_crash_handler(*iter
);
195 #if !defined(NDEBUG) && defined(__minix)
197 #endif /* !defined(NDEBUG) && defined(__minix) */