annotate win32-mingw/include/kj/exception.h @ 79:91c729825bca pa_catalina

Update build for AUDIO_COMPONENT_FIX
author Chris Cannam
date Wed, 30 Oct 2019 12:40:34 +0000
parents eccd51b72864
children
rev   line source
Chris@64 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
Chris@64 2 // Licensed under the MIT License:
Chris@64 3 //
Chris@64 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
Chris@64 5 // of this software and associated documentation files (the "Software"), to deal
Chris@64 6 // in the Software without restriction, including without limitation the rights
Chris@64 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Chris@64 8 // copies of the Software, and to permit persons to whom the Software is
Chris@64 9 // furnished to do so, subject to the following conditions:
Chris@64 10 //
Chris@64 11 // The above copyright notice and this permission notice shall be included in
Chris@64 12 // all copies or substantial portions of the Software.
Chris@64 13 //
Chris@64 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Chris@64 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Chris@64 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Chris@64 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Chris@64 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Chris@64 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Chris@64 20 // THE SOFTWARE.
Chris@64 21
Chris@64 22 #ifndef KJ_EXCEPTION_H_
Chris@64 23 #define KJ_EXCEPTION_H_
Chris@64 24
Chris@64 25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
Chris@64 26 #pragma GCC system_header
Chris@64 27 #endif
Chris@64 28
Chris@64 29 #include "memory.h"
Chris@64 30 #include "array.h"
Chris@64 31 #include "string.h"
Chris@64 32
Chris@64 33 namespace kj {
Chris@64 34
Chris@64 35 class ExceptionImpl;
Chris@64 36
Chris@64 37 class Exception {
Chris@64 38 // Exception thrown in case of fatal errors.
Chris@64 39 //
Chris@64 40 // Actually, a subclass of this which also implements std::exception will be thrown, but we hide
Chris@64 41 // that fact from the interface to avoid #including <exception>.
Chris@64 42
Chris@64 43 public:
Chris@64 44 enum class Type {
Chris@64 45 // What kind of failure?
Chris@64 46
Chris@64 47 FAILED = 0,
Chris@64 48 // Something went wrong. This is the usual error type. KJ_ASSERT and KJ_REQUIRE throw this
Chris@64 49 // error type.
Chris@64 50
Chris@64 51 OVERLOADED = 1,
Chris@64 52 // The call failed because of a temporary lack of resources. This could be space resources
Chris@64 53 // (out of memory, out of disk space) or time resources (request queue overflow, operation
Chris@64 54 // timed out).
Chris@64 55 //
Chris@64 56 // The operation might work if tried again, but it should NOT be repeated immediately as this
Chris@64 57 // may simply exacerbate the problem.
Chris@64 58
Chris@64 59 DISCONNECTED = 2,
Chris@64 60 // The call required communication over a connection that has been lost. The callee will need
Chris@64 61 // to re-establish connections and try again.
Chris@64 62
Chris@64 63 UNIMPLEMENTED = 3
Chris@64 64 // The requested method is not implemented. The caller may wish to revert to a fallback
Chris@64 65 // approach based on other methods.
Chris@64 66
Chris@64 67 // IF YOU ADD A NEW VALUE:
Chris@64 68 // - Update the stringifier.
Chris@64 69 // - Update Cap'n Proto's RPC protocol's Exception.Type enum.
Chris@64 70 };
Chris@64 71
Chris@64 72 Exception(Type type, const char* file, int line, String description = nullptr) noexcept;
Chris@64 73 Exception(Type type, String file, int line, String description = nullptr) noexcept;
Chris@64 74 Exception(const Exception& other) noexcept;
Chris@64 75 Exception(Exception&& other) = default;
Chris@64 76 ~Exception() noexcept;
Chris@64 77
Chris@64 78 const char* getFile() const { return file; }
Chris@64 79 int getLine() const { return line; }
Chris@64 80 Type getType() const { return type; }
Chris@64 81 StringPtr getDescription() const { return description; }
Chris@64 82 ArrayPtr<void* const> getStackTrace() const { return arrayPtr(trace, traceCount); }
Chris@64 83
Chris@64 84 struct Context {
Chris@64 85 // Describes a bit about what was going on when the exception was thrown.
Chris@64 86
Chris@64 87 const char* file;
Chris@64 88 int line;
Chris@64 89 String description;
Chris@64 90 Maybe<Own<Context>> next;
Chris@64 91
Chris@64 92 Context(const char* file, int line, String&& description, Maybe<Own<Context>>&& next)
Chris@64 93 : file(file), line(line), description(mv(description)), next(mv(next)) {}
Chris@64 94 Context(const Context& other) noexcept;
Chris@64 95 };
Chris@64 96
Chris@64 97 inline Maybe<const Context&> getContext() const {
Chris@64 98 KJ_IF_MAYBE(c, context) {
Chris@64 99 return **c;
Chris@64 100 } else {
Chris@64 101 return nullptr;
Chris@64 102 }
Chris@64 103 }
Chris@64 104
Chris@64 105 void wrapContext(const char* file, int line, String&& description);
Chris@64 106 // Wraps the context in a new node. This becomes the head node returned by getContext() -- it
Chris@64 107 // is expected that contexts will be added in reverse order as the exception passes up the
Chris@64 108 // callback stack.
Chris@64 109
Chris@64 110 KJ_NOINLINE void extendTrace(uint ignoreCount);
Chris@64 111 // Append the current stack trace to the exception's trace, ignoring the first `ignoreCount`
Chris@64 112 // frames (see `getStackTrace()` for discussion of `ignoreCount`).
Chris@64 113
Chris@64 114 KJ_NOINLINE void truncateCommonTrace();
Chris@64 115 // Remove the part of the stack trace which the exception shares with the caller of this method.
Chris@64 116 // This is used by the async library to remove the async infrastructure from the stack trace
Chris@64 117 // before replacing it with the async trace.
Chris@64 118
Chris@64 119 void addTrace(void* ptr);
Chris@64 120 // Append the given pointer to the backtrace, if it is not already full. This is used by the
Chris@64 121 // async library to trace through the promise chain that led to the exception.
Chris@64 122
Chris@64 123 private:
Chris@64 124 String ownFile;
Chris@64 125 const char* file;
Chris@64 126 int line;
Chris@64 127 Type type;
Chris@64 128 String description;
Chris@64 129 Maybe<Own<Context>> context;
Chris@64 130 void* trace[32];
Chris@64 131 uint traceCount;
Chris@64 132
Chris@64 133 friend class ExceptionImpl;
Chris@64 134 };
Chris@64 135
Chris@64 136 StringPtr KJ_STRINGIFY(Exception::Type type);
Chris@64 137 String KJ_STRINGIFY(const Exception& e);
Chris@64 138
Chris@64 139 // =======================================================================================
Chris@64 140
Chris@64 141 enum class LogSeverity {
Chris@64 142 INFO, // Information describing what the code is up to, which users may request to see
Chris@64 143 // with a flag like `--verbose`. Does not indicate a problem. Not printed by
Chris@64 144 // default; you must call setLogLevel(INFO) to enable.
Chris@64 145 WARNING, // A problem was detected but execution can continue with correct output.
Chris@64 146 ERROR, // Something is wrong, but execution can continue with garbage output.
Chris@64 147 FATAL, // Something went wrong, and execution cannot continue.
Chris@64 148 DBG // Temporary debug logging. See KJ_DBG.
Chris@64 149
Chris@64 150 // Make sure to update the stringifier if you add a new severity level.
Chris@64 151 };
Chris@64 152
Chris@64 153 StringPtr KJ_STRINGIFY(LogSeverity severity);
Chris@64 154
Chris@64 155 class ExceptionCallback {
Chris@64 156 // If you don't like C++ exceptions, you may implement and register an ExceptionCallback in order
Chris@64 157 // to perform your own exception handling. For example, a reasonable thing to do is to have
Chris@64 158 // onRecoverableException() set a flag indicating that an error occurred, and then check for that
Chris@64 159 // flag just before writing to storage and/or returning results to the user. If the flag is set,
Chris@64 160 // discard whatever you have and return an error instead.
Chris@64 161 //
Chris@64 162 // ExceptionCallbacks must always be allocated on the stack. When an exception is thrown, the
Chris@64 163 // newest ExceptionCallback on the calling thread's stack is called. The default implementation
Chris@64 164 // of each method calls the next-oldest ExceptionCallback for that thread. Thus the callbacks
Chris@64 165 // behave a lot like try/catch blocks, except that they are called before any stack unwinding
Chris@64 166 // occurs.
Chris@64 167
Chris@64 168 public:
Chris@64 169 ExceptionCallback();
Chris@64 170 KJ_DISALLOW_COPY(ExceptionCallback);
Chris@64 171 virtual ~ExceptionCallback() noexcept(false);
Chris@64 172
Chris@64 173 virtual void onRecoverableException(Exception&& exception);
Chris@64 174 // Called when an exception has been raised, but the calling code has the ability to continue by
Chris@64 175 // producing garbage output. This method _should_ throw the exception, but is allowed to simply
Chris@64 176 // return if garbage output is acceptable.
Chris@64 177 //
Chris@64 178 // The global default implementation throws an exception unless the library was compiled with
Chris@64 179 // -fno-exceptions, in which case it logs an error and returns.
Chris@64 180
Chris@64 181 virtual void onFatalException(Exception&& exception);
Chris@64 182 // Called when an exception has been raised and the calling code cannot continue. If this method
Chris@64 183 // returns normally, abort() will be called. The method must throw the exception to avoid
Chris@64 184 // aborting.
Chris@64 185 //
Chris@64 186 // The global default implementation throws an exception unless the library was compiled with
Chris@64 187 // -fno-exceptions, in which case it logs an error and returns.
Chris@64 188
Chris@64 189 virtual void logMessage(LogSeverity severity, const char* file, int line, int contextDepth,
Chris@64 190 String&& text);
Chris@64 191 // Called when something wants to log some debug text. `contextDepth` indicates how many levels
Chris@64 192 // of context the message passed through; it may make sense to indent the message accordingly.
Chris@64 193 //
Chris@64 194 // The global default implementation writes the text to stderr.
Chris@64 195
Chris@64 196 enum class StackTraceMode {
Chris@64 197 FULL,
Chris@64 198 // Stringifying a stack trace will attempt to determine source file and line numbers. This may
Chris@64 199 // be expensive. For example, on Linux, this shells out to `addr2line`.
Chris@64 200 //
Chris@64 201 // This is the default in debug builds.
Chris@64 202
Chris@64 203 ADDRESS_ONLY,
Chris@64 204 // Stringifying a stack trace will only generate a list of code addresses.
Chris@64 205 //
Chris@64 206 // This is the default in release builds.
Chris@64 207
Chris@64 208 NONE
Chris@64 209 // Generating a stack trace will always return an empty array.
Chris@64 210 //
Chris@64 211 // This avoids ever unwinding the stack. On Windows in particular, the stack unwinding library
Chris@64 212 // has been observed to be pretty slow, so exception-heavy code might benefit significantly
Chris@64 213 // from this setting. (But exceptions should be rare...)
Chris@64 214 };
Chris@64 215
Chris@64 216 virtual StackTraceMode stackTraceMode();
Chris@64 217 // Returns the current preferred stack trace mode.
Chris@64 218
Chris@64 219 protected:
Chris@64 220 ExceptionCallback& next;
Chris@64 221
Chris@64 222 private:
Chris@64 223 ExceptionCallback(ExceptionCallback& next);
Chris@64 224
Chris@64 225 class RootExceptionCallback;
Chris@64 226 friend ExceptionCallback& getExceptionCallback();
Chris@64 227 };
Chris@64 228
Chris@64 229 ExceptionCallback& getExceptionCallback();
Chris@64 230 // Returns the current exception callback.
Chris@64 231
Chris@64 232 KJ_NOINLINE KJ_NORETURN(void throwFatalException(kj::Exception&& exception, uint ignoreCount = 0));
Chris@64 233 // Invoke the exception callback to throw the given fatal exception. If the exception callback
Chris@64 234 // returns, abort.
Chris@64 235
Chris@64 236 KJ_NOINLINE void throwRecoverableException(kj::Exception&& exception, uint ignoreCount = 0);
Chris@64 237 // Invoke the exception callback to throw the given recoverable exception. If the exception
Chris@64 238 // callback returns, return normally.
Chris@64 239
Chris@64 240 // =======================================================================================
Chris@64 241
Chris@64 242 namespace _ { class Runnable; }
Chris@64 243
Chris@64 244 template <typename Func>
Chris@64 245 Maybe<Exception> runCatchingExceptions(Func&& func) noexcept;
Chris@64 246 // Executes the given function (usually, a lambda returning nothing) catching any exceptions that
Chris@64 247 // are thrown. Returns the Exception if there was one, or null if the operation completed normally.
Chris@64 248 // Non-KJ exceptions will be wrapped.
Chris@64 249 //
Chris@64 250 // If exception are disabled (e.g. with -fno-exceptions), this will still detect whether any
Chris@64 251 // recoverable exceptions occurred while running the function and will return those.
Chris@64 252
Chris@64 253 class UnwindDetector {
Chris@64 254 // Utility for detecting when a destructor is called due to unwind. Useful for:
Chris@64 255 // - Avoiding throwing exceptions in this case, which would terminate the program.
Chris@64 256 // - Detecting whether to commit or roll back a transaction.
Chris@64 257 //
Chris@64 258 // To use this class, either inherit privately from it or declare it as a member. The detector
Chris@64 259 // works by comparing the exception state against that when the constructor was called, so for
Chris@64 260 // an object that was actually constructed during exception unwind, it will behave as if no
Chris@64 261 // unwind is taking place. This is usually the desired behavior.
Chris@64 262
Chris@64 263 public:
Chris@64 264 UnwindDetector();
Chris@64 265
Chris@64 266 bool isUnwinding() const;
Chris@64 267 // Returns true if the current thread is in a stack unwind that it wasn't in at the time the
Chris@64 268 // object was constructed.
Chris@64 269
Chris@64 270 template <typename Func>
Chris@64 271 void catchExceptionsIfUnwinding(Func&& func) const;
Chris@64 272 // Runs the given function (e.g., a lambda). If isUnwinding() is true, any exceptions are
Chris@64 273 // caught and treated as secondary faults, meaning they are considered to be side-effects of the
Chris@64 274 // exception that is unwinding the stack. Otherwise, exceptions are passed through normally.
Chris@64 275
Chris@64 276 private:
Chris@64 277 uint uncaughtCount;
Chris@64 278
Chris@64 279 void catchExceptionsAsSecondaryFaults(_::Runnable& runnable) const;
Chris@64 280 };
Chris@64 281
Chris@64 282 namespace _ { // private
Chris@64 283
Chris@64 284 class Runnable {
Chris@64 285 public:
Chris@64 286 virtual void run() = 0;
Chris@64 287 };
Chris@64 288
Chris@64 289 template <typename Func>
Chris@64 290 class RunnableImpl: public Runnable {
Chris@64 291 public:
Chris@64 292 RunnableImpl(Func&& func): func(kj::mv(func)) {}
Chris@64 293 void run() override {
Chris@64 294 func();
Chris@64 295 }
Chris@64 296 private:
Chris@64 297 Func func;
Chris@64 298 };
Chris@64 299
Chris@64 300 Maybe<Exception> runCatchingExceptions(Runnable& runnable) noexcept;
Chris@64 301
Chris@64 302 } // namespace _ (private)
Chris@64 303
Chris@64 304 template <typename Func>
Chris@64 305 Maybe<Exception> runCatchingExceptions(Func&& func) noexcept {
Chris@64 306 _::RunnableImpl<Decay<Func>> runnable(kj::fwd<Func>(func));
Chris@64 307 return _::runCatchingExceptions(runnable);
Chris@64 308 }
Chris@64 309
Chris@64 310 template <typename Func>
Chris@64 311 void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const {
Chris@64 312 if (isUnwinding()) {
Chris@64 313 _::RunnableImpl<Decay<Func>> runnable(kj::fwd<Func>(func));
Chris@64 314 catchExceptionsAsSecondaryFaults(runnable);
Chris@64 315 } else {
Chris@64 316 func();
Chris@64 317 }
Chris@64 318 }
Chris@64 319
Chris@64 320 #define KJ_ON_SCOPE_SUCCESS(code) \
Chris@64 321 ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
Chris@64 322 KJ_DEFER(if (!KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; })
Chris@64 323 // Runs `code` if the current scope is exited normally (not due to an exception).
Chris@64 324
Chris@64 325 #define KJ_ON_SCOPE_FAILURE(code) \
Chris@64 326 ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
Chris@64 327 KJ_DEFER(if (KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; })
Chris@64 328 // Runs `code` if the current scope is exited due to an exception.
Chris@64 329
Chris@64 330 // =======================================================================================
Chris@64 331
Chris@64 332 KJ_NOINLINE ArrayPtr<void* const> getStackTrace(ArrayPtr<void*> space, uint ignoreCount);
Chris@64 333 // Attempt to get the current stack trace, returning a list of pointers to instructions. The
Chris@64 334 // returned array is a slice of `space`. Provide a larger `space` to get a deeper stack trace.
Chris@64 335 // If the platform doesn't support stack traces, returns an empty array.
Chris@64 336 //
Chris@64 337 // `ignoreCount` items will be truncated from the front of the trace. This is useful for chopping
Chris@64 338 // off a prefix of the trace that is uninteresting to the developer because it's just locations
Chris@64 339 // inside the debug infrastructure that is requesting the trace. Be careful to mark functions as
Chris@64 340 // KJ_NOINLINE if you intend to count them in `ignoreCount`. Note that, unfortunately, the
Chris@64 341 // ignored entries will still waste space in the `space` array (and the returned array's `begin()`
Chris@64 342 // is never exactly equal to `space.begin()` due to this effect, even if `ignoreCount` is zero
Chris@64 343 // since `getStackTrace()` needs to ignore its own internal frames).
Chris@64 344
Chris@64 345 String stringifyStackTrace(ArrayPtr<void* const>);
Chris@64 346 // Convert the stack trace to a string with file names and line numbers. This may involve executing
Chris@64 347 // suprocesses.
Chris@64 348
Chris@64 349 String getStackTrace();
Chris@64 350 // Get a stack trace right now and stringify it. Useful for debugging.
Chris@64 351
Chris@64 352 void printStackTraceOnCrash();
Chris@64 353 // Registers signal handlers on common "crash" signals like SIGSEGV that will (attempt to) print
Chris@64 354 // a stack trace. You should call this as early as possible on program startup. Programs using
Chris@64 355 // KJ_MAIN get this automatically.
Chris@64 356
Chris@64 357 kj::StringPtr trimSourceFilename(kj::StringPtr filename);
Chris@64 358 // Given a source code file name, trim off noisy prefixes like "src/" or
Chris@64 359 // "/ekam-provider/canonical/".
Chris@64 360
Chris@64 361 } // namespace kj
Chris@64 362
Chris@64 363 #endif // KJ_EXCEPTION_H_