toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.mm

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2007, 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 #import "OnDemandServer.h"
    32 #import "Breakpad.h"
    33 #include "common/mac/bootstrap_compat.h"
    35 #if DEBUG
    36   #define PRINT_MACH_RESULT(result_, message_) \
    37     printf(message_"%s (%d)\n", mach_error_string(result_), result_ );
    38 #if defined(MAC_OS_X_VERSION_10_5) && \
    39     MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
    40   #define PRINT_BOOTSTRAP_RESULT(result_, message_) \
    41     printf(message_"%s (%d)\n", bootstrap_strerror(result_), result_ );
    42 #else
    43   #define PRINT_BOOTSTRAP_RESULT(result_, message_) \
    44     PRINT_MACH_RESULT(result_, message_)
    45 #endif
    46 #else
    47   #define PRINT_MACH_RESULT(result_, message_)
    48   #define PRINT_BOOTSTRAP_RESULT(result_, message_)
    49 #endif
    51 //==============================================================================
    52 OnDemandServer *OnDemandServer::Create(const char *server_command,
    53                                        const char *service_name,
    54                                        bool unregister_on_cleanup,
    55                                        kern_return_t *out_result) {
    56   OnDemandServer *server = new OnDemandServer();
    58   if (!server) return NULL;
    60   kern_return_t result = server->Initialize(server_command,
    61                                             service_name,
    62                                             unregister_on_cleanup);
    64   if (out_result) {
    65     *out_result = result;
    66   }
    68   if (result == KERN_SUCCESS) {
    69     return server;
    70   }
    72   delete server;
    73   return NULL;
    74 };
    76 //==============================================================================
    77 kern_return_t OnDemandServer::Initialize(const char *server_command,
    78                                          const char *service_name,
    79                                          bool unregister_on_cleanup) {
    80   unregister_on_cleanup_ = unregister_on_cleanup;
    82   mach_port_t self_task = mach_task_self();
    84   mach_port_t bootstrap_port;
    85   kern_return_t kr = task_get_bootstrap_port(self_task, &bootstrap_port);
    86   if (kr != KERN_SUCCESS) {
    87     PRINT_MACH_RESULT(kr, "task_get_bootstrap_port(): ");
    88     return kr;
    89   }
    91   mach_port_t bootstrap_subset_port;
    92   kr = bootstrap_subset(bootstrap_port, self_task, &bootstrap_subset_port);
    93   if (kr != BOOTSTRAP_SUCCESS) {
    94     PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_subset(): ");
    95     return kr;
    96   }
    98   // The inspector will be invoked with its bootstrap port set to the subset,
    99   // but the sender will need access to the original bootstrap port. Although
   100   // the original port is the subset's parent, bootstrap_parent can't be used
   101   // because it requires extra privileges. Stash the original bootstrap port
   102   // in the subset by registering it under a known name. The inspector will
   103   // recover this port and set it as its own bootstrap port in Inspector.mm
   104   // Inspector::ResetBootstrapPort.
   105   kr = breakpad::BootstrapRegister(
   106       bootstrap_subset_port,
   107       const_cast<char*>(BREAKPAD_BOOTSTRAP_PARENT_PORT),
   108       bootstrap_port);
   109   if (kr != BOOTSTRAP_SUCCESS) {
   110     PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_register(): ");
   111     return kr;
   112   }
   114   kr = bootstrap_create_server(bootstrap_subset_port,
   115                                const_cast<char*>(server_command),
   116                                geteuid(),       // server uid
   117                                true,
   118                                &server_port_);
   119   if (kr != BOOTSTRAP_SUCCESS) {
   120     PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_create_server(): ");
   121     return kr;
   122   }
   124   strlcpy(service_name_, service_name, sizeof(service_name_));
   126 #pragma clang diagnostic push
   127 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
   128   // Create a service called service_name, and return send rights to
   129   // that port in service_port_.
   130   kr = bootstrap_create_service(server_port_,
   131                                 const_cast<char*>(service_name),
   132                                 &service_port_);
   133 #pragma clang diagnostic pop
   134   if (kr != BOOTSTRAP_SUCCESS) {
   135     PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_create_service(): ");
   137     // perhaps the service has already been created - try to look it up
   138     kr = bootstrap_look_up(bootstrap_port, (char*)service_name, &service_port_);
   140     if (kr != BOOTSTRAP_SUCCESS) {
   141       PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_look_up(): ");
   142       Unregister();  // clean up server port
   143       return kr;
   144     }
   145   }
   147   return KERN_SUCCESS;
   148 }
   150 //==============================================================================
   151 OnDemandServer::~OnDemandServer() {
   152   if (unregister_on_cleanup_) {
   153     Unregister();
   154   }
   155 }
   157 //==============================================================================
   158 void OnDemandServer::LaunchOnDemand() {
   159   // We need to do this, since the launched server is another process
   160   // and holding on to this port delays launching until the current process
   161   // exits!
   162   mach_port_deallocate(mach_task_self(), server_port_);
   163   server_port_ = MACH_PORT_DEAD;
   165   // Now, the service is still registered and all we need to do is send
   166   // a mach message to the service port in order to launch the server.
   167 }
   169 //==============================================================================
   170 void OnDemandServer::Unregister() {
   171   if (service_port_ != MACH_PORT_NULL) {
   172     mach_port_deallocate(mach_task_self(), service_port_);
   173     service_port_ = MACH_PORT_NULL;
   174   }
   176   if (server_port_ != MACH_PORT_NULL) {
   177     // unregister the service
   178     kern_return_t kr = breakpad::BootstrapRegister(server_port_,
   179                                                    service_name_,
   180                                                    MACH_PORT_NULL);
   182     if (kr != KERN_SUCCESS) {
   183       PRINT_MACH_RESULT(kr, "Breakpad UNREGISTER : bootstrap_register() : ");
   184     }
   186     mach_port_deallocate(mach_task_self(), server_port_);
   187     server_port_ = MACH_PORT_NULL;
   188   }
   189 }

mercurial