You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					364 lines
				
				14 KiB
			
		
		
			
		
	
	
					364 lines
				
				14 KiB
			| 
								 
											6 years ago
										 
									 | 
							
								// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
							 | 
						||
| 
								 | 
							
								// Licensed under the MIT License:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Permission is hereby granted, free of charge, to any person obtaining a copy
							 | 
						||
| 
								 | 
							
								// of this software and associated documentation files (the "Software"), to deal
							 | 
						||
| 
								 | 
							
								// in the Software without restriction, including without limitation the rights
							 | 
						||
| 
								 | 
							
								// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
							 | 
						||
| 
								 | 
							
								// copies of the Software, and to permit persons to whom the Software is
							 | 
						||
| 
								 | 
							
								// furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								// all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
							 | 
						||
| 
								 | 
							
								// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
							 | 
						||
| 
								 | 
							
								// THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef KJ_EXCEPTION_H_
							 | 
						||
| 
								 | 
							
								#define KJ_EXCEPTION_H_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
							 | 
						||
| 
								 | 
							
								#pragma GCC system_header
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "memory.h"
							 | 
						||
| 
								 | 
							
								#include "array.h"
							 | 
						||
| 
								 | 
							
								#include "string.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace kj {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ExceptionImpl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Exception {
							 | 
						||
| 
								 | 
							
								  // Exception thrown in case of fatal errors.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // Actually, a subclass of this which also implements std::exception will be thrown, but we hide
							 | 
						||
| 
								 | 
							
								  // that fact from the interface to avoid #including <exception>.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  enum class Type {
							 | 
						||
| 
								 | 
							
								    // What kind of failure?
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    FAILED = 0,
							 | 
						||
| 
								 | 
							
								    // Something went wrong. This is the usual error type. KJ_ASSERT and KJ_REQUIRE throw this
							 | 
						||
| 
								 | 
							
								    // error type.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    OVERLOADED = 1,
							 | 
						||
| 
								 | 
							
								    // The call failed because of a temporary lack of resources. This could be space resources
							 | 
						||
| 
								 | 
							
								    // (out of memory, out of disk space) or time resources (request queue overflow, operation
							 | 
						||
| 
								 | 
							
								    // timed out).
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // The operation might work if tried again, but it should NOT be repeated immediately as this
							 | 
						||
| 
								 | 
							
								    // may simply exacerbate the problem.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DISCONNECTED = 2,
							 | 
						||
| 
								 | 
							
								    // The call required communication over a connection that has been lost. The callee will need
							 | 
						||
| 
								 | 
							
								    // to re-establish connections and try again.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    UNIMPLEMENTED = 3
							 | 
						||
| 
								 | 
							
								    // The requested method is not implemented. The caller may wish to revert to a fallback
							 | 
						||
| 
								 | 
							
								    // approach based on other methods.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // IF YOU ADD A NEW VALUE:
							 | 
						||
| 
								 | 
							
								    // - Update the stringifier.
							 | 
						||
| 
								 | 
							
								    // - Update Cap'n Proto's RPC protocol's Exception.Type enum.
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Exception(Type type, const char* file, int line, String description = nullptr) noexcept;
							 | 
						||
| 
								 | 
							
								  Exception(Type type, String file, int line, String description = nullptr) noexcept;
							 | 
						||
| 
								 | 
							
								  Exception(const Exception& other) noexcept;
							 | 
						||
| 
								 | 
							
								  Exception(Exception&& other) = default;
							 | 
						||
| 
								 | 
							
								  ~Exception() noexcept;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const char* getFile() const { return file; }
							 | 
						||
| 
								 | 
							
								  int getLine() const { return line; }
							 | 
						||
| 
								 | 
							
								  Type getType() const { return type; }
							 | 
						||
| 
								 | 
							
								  StringPtr getDescription() const { return description; }
							 | 
						||
| 
								 | 
							
								  ArrayPtr<void* const> getStackTrace() const { return arrayPtr(trace, traceCount); }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  struct Context {
							 | 
						||
| 
								 | 
							
								    // Describes a bit about what was going on when the exception was thrown.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const char* file;
							 | 
						||
| 
								 | 
							
								    int line;
							 | 
						||
| 
								 | 
							
								    String description;
							 | 
						||
| 
								 | 
							
								    Maybe<Own<Context>> next;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Context(const char* file, int line, String&& description, Maybe<Own<Context>>&& next)
							 | 
						||
| 
								 | 
							
								        : file(file), line(line), description(mv(description)), next(mv(next)) {}
							 | 
						||
| 
								 | 
							
								    Context(const Context& other) noexcept;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  inline Maybe<const Context&> getContext() const {
							 | 
						||
| 
								 | 
							
								    KJ_IF_MAYBE(c, context) {
							 | 
						||
| 
								 | 
							
								      return **c;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return nullptr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void wrapContext(const char* file, int line, String&& description);
							 | 
						||
| 
								 | 
							
								  // Wraps the context in a new node.  This becomes the head node returned by getContext() -- it
							 | 
						||
| 
								 | 
							
								  // is expected that contexts will be added in reverse order as the exception passes up the
							 | 
						||
| 
								 | 
							
								  // callback stack.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  KJ_NOINLINE void extendTrace(uint ignoreCount);
							 | 
						||
| 
								 | 
							
								  // Append the current stack trace to the exception's trace, ignoring the first `ignoreCount`
							 | 
						||
| 
								 | 
							
								  // frames (see `getStackTrace()` for discussion of `ignoreCount`).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  KJ_NOINLINE void truncateCommonTrace();
							 | 
						||
| 
								 | 
							
								  // Remove the part of the stack trace which the exception shares with the caller of this method.
							 | 
						||
| 
								 | 
							
								  // This is used by the async library to remove the async infrastructure from the stack trace
							 | 
						||
| 
								 | 
							
								  // before replacing it with the async trace.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void addTrace(void* ptr);
							 | 
						||
| 
								 | 
							
								  // Append the given pointer to the backtrace, if it is not already full. This is used by the
							 | 
						||
| 
								 | 
							
								  // async library to trace through the promise chain that led to the exception.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  String ownFile;
							 | 
						||
| 
								 | 
							
								  const char* file;
							 | 
						||
| 
								 | 
							
								  int line;
							 | 
						||
| 
								 | 
							
								  Type type;
							 | 
						||
| 
								 | 
							
								  String description;
							 | 
						||
| 
								 | 
							
								  Maybe<Own<Context>> context;
							 | 
						||
| 
								 | 
							
								  void* trace[32];
							 | 
						||
| 
								 | 
							
								  uint traceCount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  friend class ExceptionImpl;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								StringPtr KJ_STRINGIFY(Exception::Type type);
							 | 
						||
| 
								 | 
							
								String KJ_STRINGIFY(const Exception& e);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// =======================================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum class LogSeverity {
							 | 
						||
| 
								 | 
							
								  INFO,      // Information describing what the code is up to, which users may request to see
							 | 
						||
| 
								 | 
							
								             // with a flag like `--verbose`.  Does not indicate a problem.  Not printed by
							 | 
						||
| 
								 | 
							
								             // default; you must call setLogLevel(INFO) to enable.
							 | 
						||
| 
								 | 
							
								  WARNING,   // A problem was detected but execution can continue with correct output.
							 | 
						||
| 
								 | 
							
								  ERROR,     // Something is wrong, but execution can continue with garbage output.
							 | 
						||
| 
								 | 
							
								  FATAL,     // Something went wrong, and execution cannot continue.
							 | 
						||
| 
								 | 
							
								  DBG        // Temporary debug logging.  See KJ_DBG.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Make sure to update the stringifier if you add a new severity level.
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								StringPtr KJ_STRINGIFY(LogSeverity severity);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ExceptionCallback {
							 | 
						||
| 
								 | 
							
								  // If you don't like C++ exceptions, you may implement and register an ExceptionCallback in order
							 | 
						||
| 
								 | 
							
								  // to perform your own exception handling.  For example, a reasonable thing to do is to have
							 | 
						||
| 
								 | 
							
								  // onRecoverableException() set a flag indicating that an error occurred, and then check for that
							 | 
						||
| 
								 | 
							
								  // flag just before writing to storage and/or returning results to the user.  If the flag is set,
							 | 
						||
| 
								 | 
							
								  // discard whatever you have and return an error instead.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // ExceptionCallbacks must always be allocated on the stack.  When an exception is thrown, the
							 | 
						||
| 
								 | 
							
								  // newest ExceptionCallback on the calling thread's stack is called.  The default implementation
							 | 
						||
| 
								 | 
							
								  // of each method calls the next-oldest ExceptionCallback for that thread.  Thus the callbacks
							 | 
						||
| 
								 | 
							
								  // behave a lot like try/catch blocks, except that they are called before any stack unwinding
							 | 
						||
| 
								 | 
							
								  // occurs.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  ExceptionCallback();
							 | 
						||
| 
								 | 
							
								  KJ_DISALLOW_COPY(ExceptionCallback);
							 | 
						||
| 
								 | 
							
								  virtual ~ExceptionCallback() noexcept(false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void onRecoverableException(Exception&& exception);
							 | 
						||
| 
								 | 
							
								  // Called when an exception has been raised, but the calling code has the ability to continue by
							 | 
						||
| 
								 | 
							
								  // producing garbage output.  This method _should_ throw the exception, but is allowed to simply
							 | 
						||
| 
								 | 
							
								  // return if garbage output is acceptable.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // The global default implementation throws an exception unless the library was compiled with
							 | 
						||
| 
								 | 
							
								  // -fno-exceptions, in which case it logs an error and returns.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void onFatalException(Exception&& exception);
							 | 
						||
| 
								 | 
							
								  // Called when an exception has been raised and the calling code cannot continue.  If this method
							 | 
						||
| 
								 | 
							
								  // returns normally, abort() will be called.  The method must throw the exception to avoid
							 | 
						||
| 
								 | 
							
								  // aborting.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // The global default implementation throws an exception unless the library was compiled with
							 | 
						||
| 
								 | 
							
								  // -fno-exceptions, in which case it logs an error and returns.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual void logMessage(LogSeverity severity, const char* file, int line, int contextDepth,
							 | 
						||
| 
								 | 
							
								                          String&& text);
							 | 
						||
| 
								 | 
							
								  // Called when something wants to log some debug text.  `contextDepth` indicates how many levels
							 | 
						||
| 
								 | 
							
								  // of context the message passed through; it may make sense to indent the message accordingly.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // The global default implementation writes the text to stderr.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  enum class StackTraceMode {
							 | 
						||
| 
								 | 
							
								    FULL,
							 | 
						||
| 
								 | 
							
								    // Stringifying a stack trace will attempt to determine source file and line numbers. This may
							 | 
						||
| 
								 | 
							
								    // be expensive. For example, on Linux, this shells out to `addr2line`.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // This is the default in debug builds.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ADDRESS_ONLY,
							 | 
						||
| 
								 | 
							
								    // Stringifying a stack trace will only generate a list of code addresses.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // This is the default in release builds.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    NONE
							 | 
						||
| 
								 | 
							
								    // Generating a stack trace will always return an empty array.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // This avoids ever unwinding the stack. On Windows in particular, the stack unwinding library
							 | 
						||
| 
								 | 
							
								    // has been observed to be pretty slow, so exception-heavy code might benefit significantly
							 | 
						||
| 
								 | 
							
								    // from this setting. (But exceptions should be rare...)
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  virtual StackTraceMode stackTraceMode();
							 | 
						||
| 
								 | 
							
								  // Returns the current preferred stack trace mode.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
								  ExceptionCallback& next;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  ExceptionCallback(ExceptionCallback& next);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class RootExceptionCallback;
							 | 
						||
| 
								 | 
							
								  friend ExceptionCallback& getExceptionCallback();
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ExceptionCallback& getExceptionCallback();
							 | 
						||
| 
								 | 
							
								// Returns the current exception callback.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KJ_NOINLINE KJ_NORETURN(void throwFatalException(kj::Exception&& exception, uint ignoreCount = 0));
							 | 
						||
| 
								 | 
							
								// Invoke the exception callback to throw the given fatal exception.  If the exception callback
							 | 
						||
| 
								 | 
							
								// returns, abort.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KJ_NOINLINE void throwRecoverableException(kj::Exception&& exception, uint ignoreCount = 0);
							 | 
						||
| 
								 | 
							
								// Invoke the exception callback to throw the given recoverable exception.  If the exception
							 | 
						||
| 
								 | 
							
								// callback returns, return normally.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// =======================================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace _ { class Runnable; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								Maybe<Exception> runCatchingExceptions(Func&& func) noexcept;
							 | 
						||
| 
								 | 
							
								// Executes the given function (usually, a lambda returning nothing) catching any exceptions that
							 | 
						||
| 
								 | 
							
								// are thrown.  Returns the Exception if there was one, or null if the operation completed normally.
							 | 
						||
| 
								 | 
							
								// Non-KJ exceptions will be wrapped.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// If exception are disabled (e.g. with -fno-exceptions), this will still detect whether any
							 | 
						||
| 
								 | 
							
								// recoverable exceptions occurred while running the function and will return those.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class UnwindDetector {
							 | 
						||
| 
								 | 
							
								  // Utility for detecting when a destructor is called due to unwind.  Useful for:
							 | 
						||
| 
								 | 
							
								  // - Avoiding throwing exceptions in this case, which would terminate the program.
							 | 
						||
| 
								 | 
							
								  // - Detecting whether to commit or roll back a transaction.
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // To use this class, either inherit privately from it or declare it as a member.  The detector
							 | 
						||
| 
								 | 
							
								  // works by comparing the exception state against that when the constructor was called, so for
							 | 
						||
| 
								 | 
							
								  // an object that was actually constructed during exception unwind, it will behave as if no
							 | 
						||
| 
								 | 
							
								  // unwind is taking place.  This is usually the desired behavior.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  UnwindDetector();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool isUnwinding() const;
							 | 
						||
| 
								 | 
							
								  // Returns true if the current thread is in a stack unwind that it wasn't in at the time the
							 | 
						||
| 
								 | 
							
								  // object was constructed.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  template <typename Func>
							 | 
						||
| 
								 | 
							
								  void catchExceptionsIfUnwinding(Func&& func) const;
							 | 
						||
| 
								 | 
							
								  // Runs the given function (e.g., a lambda).  If isUnwinding() is true, any exceptions are
							 | 
						||
| 
								 | 
							
								  // caught and treated as secondary faults, meaning they are considered to be side-effects of the
							 | 
						||
| 
								 | 
							
								  // exception that is unwinding the stack.  Otherwise, exceptions are passed through normally.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  uint uncaughtCount;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void catchExceptionsAsSecondaryFaults(_::Runnable& runnable) const;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace _ {  // private
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class Runnable {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  virtual void run() = 0;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								class RunnableImpl: public Runnable {
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  RunnableImpl(Func&& func): func(kj::mv(func)) {}
							 | 
						||
| 
								 | 
							
								  void run() override {
							 | 
						||
| 
								 | 
							
								    func();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  Func func;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Maybe<Exception> runCatchingExceptions(Runnable& runnable) noexcept;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace _ (private)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								Maybe<Exception> runCatchingExceptions(Func&& func) noexcept {
							 | 
						||
| 
								 | 
							
								  _::RunnableImpl<Decay<Func>> runnable(kj::fwd<Func>(func));
							 | 
						||
| 
								 | 
							
								  return _::runCatchingExceptions(runnable);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Func>
							 | 
						||
| 
								 | 
							
								void UnwindDetector::catchExceptionsIfUnwinding(Func&& func) const {
							 | 
						||
| 
								 | 
							
								  if (isUnwinding()) {
							 | 
						||
| 
								 | 
							
								    _::RunnableImpl<Decay<Func>> runnable(kj::fwd<Func>(func));
							 | 
						||
| 
								 | 
							
								    catchExceptionsAsSecondaryFaults(runnable);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    func();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KJ_ON_SCOPE_SUCCESS(code) \
							 | 
						||
| 
								 | 
							
								  ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
							 | 
						||
| 
								 | 
							
								  KJ_DEFER(if (!KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; })
							 | 
						||
| 
								 | 
							
								// Runs `code` if the current scope is exited normally (not due to an exception).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KJ_ON_SCOPE_FAILURE(code) \
							 | 
						||
| 
								 | 
							
								  ::kj::UnwindDetector KJ_UNIQUE_NAME(_kjUnwindDetector); \
							 | 
						||
| 
								 | 
							
								  KJ_DEFER(if (KJ_UNIQUE_NAME(_kjUnwindDetector).isUnwinding()) { code; })
							 | 
						||
| 
								 | 
							
								// Runs `code` if the current scope is exited due to an exception.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// =======================================================================================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								KJ_NOINLINE ArrayPtr<void* const> getStackTrace(ArrayPtr<void*> space, uint ignoreCount);
							 | 
						||
| 
								 | 
							
								// Attempt to get the current stack trace, returning a list of pointers to instructions. The
							 | 
						||
| 
								 | 
							
								// returned array is a slice of `space`. Provide a larger `space` to get a deeper stack trace.
							 | 
						||
| 
								 | 
							
								// If the platform doesn't support stack traces, returns an empty array.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// `ignoreCount` items will be truncated from the front of the trace. This is useful for chopping
							 | 
						||
| 
								 | 
							
								// off a prefix of the trace that is uninteresting to the developer because it's just locations
							 | 
						||
| 
								 | 
							
								// inside the debug infrastructure that is requesting the trace. Be careful to mark functions as
							 | 
						||
| 
								 | 
							
								// KJ_NOINLINE if you intend to count them in `ignoreCount`. Note that, unfortunately, the
							 | 
						||
| 
								 | 
							
								// ignored entries will still waste space in the `space` array (and the returned array's `begin()`
							 | 
						||
| 
								 | 
							
								// is never exactly equal to `space.begin()` due to this effect, even if `ignoreCount` is zero
							 | 
						||
| 
								 | 
							
								// since `getStackTrace()` needs to ignore its own internal frames).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								String stringifyStackTrace(ArrayPtr<void* const>);
							 | 
						||
| 
								 | 
							
								// Convert the stack trace to a string with file names and line numbers. This may involve executing
							 | 
						||
| 
								 | 
							
								// suprocesses.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								String getStackTrace();
							 | 
						||
| 
								 | 
							
								// Get a stack trace right now and stringify it. Useful for debugging.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void printStackTraceOnCrash();
							 | 
						||
| 
								 | 
							
								// Registers signal handlers on common "crash" signals like SIGSEGV that will (attempt to) print
							 | 
						||
| 
								 | 
							
								// a stack trace. You should call this as early as possible on program startup. Programs using
							 | 
						||
| 
								 | 
							
								// KJ_MAIN get this automatically.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								kj::StringPtr trimSourceFilename(kj::StringPtr filename);
							 | 
						||
| 
								 | 
							
								// Given a source code file name, trim off noisy prefixes like "src/" or
							 | 
						||
| 
								 | 
							
								// "/ekam-provider/canonical/".
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace kj
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  // KJ_EXCEPTION_H_
							 |