toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 // Copyright (c) 2006, Google Inc.
     2 // All rights reserved.
     3 //
     4 // Redistribution and use in source and binary forms, with or without
     5 // modification, are permitted provided that the following conditions are
     6 // met:
     7 //
     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
    11 // copyright notice, this list of conditions and the following disclaimer
    12 // in the documentation and/or other materials provided with the
    13 // distribution.
    14 //     * Neither the name of Google Inc. nor the names of its
    15 // contributors may be used to endorse or promote products derived from
    16 // this software without specific prior written permission.
    17 //
    18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    30 // exception_handler.h:  MacOS exception handler
    31 // This class can install a Mach exception port handler to trap most common
    32 // programming errors.  If an exception occurs, a minidump file will be
    33 // generated which contains detailed information about the process and the
    34 // exception.
    36 #ifndef CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
    37 #define CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__
    39 #include <mach/mach.h>
    40 #include <TargetConditionals.h>
    42 #include <string>
    44 #include "common/scoped_ptr.h"
    46 #if !TARGET_OS_IPHONE
    47 #include "client/mac/crash_generation/crash_generation_client.h"
    48 #endif
    50 namespace google_breakpad {
    52 using std::string;
    54 struct ExceptionParameters;
    56 enum HandlerThreadMessage {
    57   // Message ID telling the handler thread to write a dump.
    58   kWriteDumpMessage = 0,
    59   // Message ID telling the handler thread to write a dump and include
    60   // an exception stream.
    61   kWriteDumpWithExceptionMessage = 1,
    62   // Message ID telling the handler thread to quit.
    63   kShutdownMessage = 2
    64 };
    66 class ExceptionHandler {
    67  public:
    68   // A callback function to run before Breakpad performs any substantial
    69   // processing of an exception.  A FilterCallback is called before writing
    70   // a minidump.  context is the parameter supplied by the user as
    71   // callback_context when the handler was created.
    72   //
    73   // If a FilterCallback returns true, Breakpad will continue processing,
    74   // attempting to write a minidump.  If a FilterCallback returns false, Breakpad
    75   // will immediately report the exception as unhandled without writing a
    76   // minidump, allowing another handler the opportunity to handle it.
    77   typedef bool (*FilterCallback)(void *context);
    79   // A callback function to run after the minidump has been written.
    80   // |minidump_id| is a unique id for the dump, so the minidump
    81   // file is <dump_dir>/<minidump_id>.dmp.
    82   // |context| is the value passed into the constructor.
    83   // |succeeded| indicates whether a minidump file was successfully written.
    84   // Return true if the exception was fully handled and breakpad should exit.
    85   // Return false to allow any other exception handlers to process the
    86   // exception.
    87   typedef bool (*MinidumpCallback)(const char *dump_dir,
    88                                    const char *minidump_id,
    89                                    void *context, bool succeeded);
    91   // A callback function which will be called directly if an exception occurs.
    92   // This bypasses the minidump file writing and simply gives the client
    93   // the exception information.
    94   typedef bool (*DirectCallback)( void *context,
    95                                   int exception_type,
    96                                   int exception_code,
    97                                   int exception_subcode,
    98                                   mach_port_t thread_name);
   100   // Creates a new ExceptionHandler instance to handle writing minidumps.
   101   // Minidump files will be written to dump_path, and the optional callback
   102   // is called after writing the dump file, as described above.
   103   // If install_handler is true, then a minidump will be written whenever
   104   // an unhandled exception occurs.  If it is false, minidumps will only
   105   // be written when WriteMinidump is called.
   106   // If port_name is non-NULL, attempt to perform out-of-process dump generation
   107   // If port_name is NULL, in-process dump generation will be used.
   108   ExceptionHandler(const string &dump_path,
   109                    FilterCallback filter, MinidumpCallback callback,
   110                    void *callback_context, bool install_handler,
   111 		   const char *port_name);
   113   // A special constructor if we want to bypass minidump writing and
   114   // simply get a callback with the exception information.
   115   ExceptionHandler(DirectCallback callback,
   116                    void *callback_context,
   117                    bool install_handler);
   119   ~ExceptionHandler();
   121   // Get and set the minidump path.
   122   string dump_path() const { return dump_path_; }
   123   void set_dump_path(const string &dump_path) {
   124     dump_path_ = dump_path;
   125     dump_path_c_ = dump_path_.c_str();
   126     UpdateNextID();  // Necessary to put dump_path_ in next_minidump_path_.
   127   }
   129   // Writes a minidump immediately.  This can be used to capture the
   130   // execution state independently of a crash.  Returns true on success.
   131   bool WriteMinidump() {
   132     return WriteMinidump(false);
   133   }
   135   bool WriteMinidump(bool write_exception_stream);
   137   // Convenience form of WriteMinidump which does not require an
   138   // ExceptionHandler instance.
   139   static bool WriteMinidump(const string &dump_path, MinidumpCallback callback,
   140                             void *callback_context) {
   141     return WriteMinidump(dump_path, false, callback, callback_context);
   142   }
   144   static bool WriteMinidump(const string &dump_path,
   145                             bool write_exception_stream,
   146                             MinidumpCallback callback,
   147                             void *callback_context);
   149   // Write a minidump of child immediately. This can be used to capture
   150   // the execution state of a child process independently of a crash.
   151   static bool WriteMinidumpForChild(mach_port_t child,
   152 				    mach_port_t child_blamed_thread,
   153 				    const std::string &dump_path,
   154 				    MinidumpCallback callback,
   155 				    void *callback_context);
   157   // Returns whether out-of-process dump generation is used or not.
   158   bool IsOutOfProcess() const {
   159 #if TARGET_OS_IPHONE
   160     return false;
   161 #else
   162     return crash_generation_client_.get() != NULL;
   163 #endif
   164   }
   166  private:
   167   // Install the mach exception handler
   168   bool InstallHandler();
   170   // Uninstall the mach exception handler (if any)
   171   bool UninstallHandler(bool in_exception);
   173   // Setup the handler thread, and if |install_handler| is true, install the
   174   // mach exception port handler
   175   bool Setup(bool install_handler);
   177   // Uninstall the mach exception handler (if any) and terminate the helper
   178   // thread
   179   bool Teardown();
   181   // Send a mach message to the exception handler.  Return true on
   182   // success, false otherwise.
   183   bool SendMessageToHandlerThread(HandlerThreadMessage message_id);
   185   // All minidump writing goes through this one routine.
   186   // |task_context| can be NULL. If not, it will be used to retrieve the
   187   // context of the current thread, instead of using |thread_get_state|.
   188   bool WriteMinidumpWithException(int exception_type,
   189                                   int exception_code,
   190                                   int exception_subcode,
   191                                   ucontext_t *task_context,
   192                                   mach_port_t thread_name,
   193                                   bool exit_after_write,
   194                                   bool report_current_thread);
   196   // When installed, this static function will be call from a newly created
   197   // pthread with |this| as the argument
   198   static void *WaitForMessage(void *exception_handler_class);
   200   // Signal handler for SIGABRT.
   201   static void SignalHandler(int sig, siginfo_t* info, void* uc);
   203   // disallow copy ctor and operator=
   204   explicit ExceptionHandler(const ExceptionHandler &);
   205   void operator=(const ExceptionHandler &);
   207   // Generates a new ID and stores it in next_minidump_id_, and stores the
   208   // path of the next minidump to be written in next_minidump_path_.
   209   void UpdateNextID();
   211   // These functions will suspend/resume all threads except for the
   212   // reporting thread
   213   bool SuspendThreads();
   214   bool ResumeThreads();
   216   // The destination directory for the minidump
   217   string dump_path_;
   219   // The basename of the next minidump w/o extension
   220   string next_minidump_id_;
   222   // The full path to the next minidump to be written, including extension
   223   string next_minidump_path_;
   225   // Pointers to the UTF-8 versions of above
   226   const char *dump_path_c_;
   227   const char *next_minidump_id_c_;
   228   const char *next_minidump_path_c_;
   230   // The callback function and pointer to be passed back after the minidump
   231   // has been written
   232   FilterCallback filter_;
   233   MinidumpCallback callback_;
   234   void *callback_context_;
   236   // The callback function to be passed back when we don't want a minidump
   237   // file to be written
   238   DirectCallback directCallback_;
   240   // The thread that is created for the handler
   241   pthread_t handler_thread_;
   243   // The port that is waiting on an exception message to be sent, if the
   244   // handler is installed
   245   mach_port_t handler_port_;
   247   // These variables save the previous exception handler's data so that it
   248   // can be re-installed when this handler is uninstalled
   249   ExceptionParameters *previous_;
   251   // True, if we've installed the exception handler
   252   bool installed_exception_handler_;
   254   // True, if we're in the process of uninstalling the exception handler and
   255   // the thread.
   256   bool is_in_teardown_;
   258   // Save the last result of the last minidump
   259   bool last_minidump_write_result_;
   261   // A mutex for use when writing out a minidump that was requested on a
   262   // thread other than the exception handler.
   263   pthread_mutex_t minidump_write_mutex_;
   265   // True, if we're using the mutext to indicate when mindump writing occurs
   266   bool use_minidump_write_mutex_;
   268   // Old signal handler for SIGABRT. Used to be able to restore it when
   269   // uninstalling.
   270   scoped_ptr<struct sigaction> old_handler_;
   272 #if !TARGET_OS_IPHONE
   273   // Client for out-of-process dump generation.
   274   scoped_ptr<CrashGenerationClient> crash_generation_client_;
   275 #endif
   276 };
   278 }  // namespace google_breakpad
   280 #endif  // CLIENT_MAC_HANDLER_EXCEPTION_HANDLER_H__

mercurial