| OLD | NEW | 
|---|
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 
| 2 // | 2 // | 
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. | 
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at | 
| 6 // | 6 // | 
| 7 //     http://www.apache.org/licenses/LICENSE-2.0 | 7 //     http://www.apache.org/licenses/LICENSE-2.0 | 
| 8 // | 8 // | 
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software | 
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 31 #include "util/stdlib/string_number_conversion.h" | 31 #include "util/stdlib/string_number_conversion.h" | 
| 32 #include "util/string/split_string.h" | 32 #include "util/string/split_string.h" | 
| 33 #include "util/synchronization/semaphore.h" | 33 #include "util/synchronization/semaphore.h" | 
| 34 | 34 | 
| 35 #if defined(OS_MACOSX) | 35 #if defined(OS_MACOSX) | 
| 36 #include <libgen.h> | 36 #include <libgen.h> | 
| 37 #include "base/mac/scoped_mach_port.h" | 37 #include "base/mac/scoped_mach_port.h" | 
| 38 #include "handler/mac/crash_report_exception_handler.h" | 38 #include "handler/mac/crash_report_exception_handler.h" | 
| 39 #include "handler/mac/exception_handler_server.h" | 39 #include "handler/mac/exception_handler_server.h" | 
| 40 #include "util/mach/child_port_handshake.h" | 40 #include "util/mach/child_port_handshake.h" | 
|  | 41 #include "util/mach/mach_extensions.h" | 
| 41 #include "util/posix/close_stdio.h" | 42 #include "util/posix/close_stdio.h" | 
| 42 #elif defined(OS_WIN) | 43 #elif defined(OS_WIN) | 
| 43 #include <windows.h> | 44 #include <windows.h> | 
| 44 #include "handler/win/crash_report_exception_handler.h" | 45 #include "handler/win/crash_report_exception_handler.h" | 
| 45 #include "util/win/exception_handler_server.h" | 46 #include "util/win/exception_handler_server.h" | 
| 46 #endif  // OS_MACOSX | 47 #endif  // OS_MACOSX | 
| 47 | 48 | 
| 48 namespace crashpad { | 49 namespace crashpad { | 
| 49 namespace { | 50 namespace { | 
| 50 | 51 | 
| 51 void Usage(const base::FilePath& me) { | 52 void Usage(const base::FilePath& me) { | 
| 52   fprintf(stderr, | 53   fprintf(stderr, | 
| 53 "Usage: %" PRFilePath " [OPTION]...\n" | 54 "Usage: %" PRFilePath " [OPTION]...\n" | 
| 54 "Crashpad's exception handler server.\n" | 55 "Crashpad's exception handler server.\n" | 
| 55 "\n" | 56 "\n" | 
| 56 "      --annotation=KEY=VALUE  set a process annotation in each crash report\n" | 57 "      --annotation=KEY=VALUE  set a process annotation in each crash report\n" | 
| 57 "      --database=PATH         store the crash report database at PATH\n" | 58 "      --database=PATH         store the crash report database at PATH\n" | 
| 58 #if defined(OS_MACOSX) | 59 #if defined(OS_MACOSX) | 
| 59 "      --handshake-fd=FD       establish communication with the client over FD\n
     " | 60 "      --handshake-fd=FD       establish communication with the client over FD\n
     " | 
|  | 61 "      --mach-service=SERVICE  register SERVICE with the bootstrap server\n" | 
| 60 "      --reset-own-crash-exception-port-to-system-default\n" | 62 "      --reset-own-crash-exception-port-to-system-default\n" | 
| 61 "                              reset the server's exception handler to default\n
     " | 63 "                              reset the server's exception handler to default\n
     " | 
| 62 #elif defined(OS_WIN) | 64 #elif defined(OS_WIN) | 
| 63 "      --persistent            continue running after all clients exit\n" | 65 "      --persistent            continue running after all clients exit\n" | 
| 64 "      --pipe-name=PIPE        communicate with the client over PIPE\n" | 66 "      --pipe-name=PIPE        communicate with the client over PIPE\n" | 
| 65 #endif  // OS_MACOSX | 67 #endif  // OS_MACOSX | 
| 66 "      --url=URL               send crash reports to this Breakpad server URL,\n
     " | 68 "      --url=URL               send crash reports to this Breakpad server URL,\n
     " | 
| 67 "                              only if uploads are enabled for the database\n" | 69 "                              only if uploads are enabled for the database\n" | 
| 68 "      --help                  display this help and exit\n" | 70 "      --help                  display this help and exit\n" | 
| 69 "      --version               output version information and exit\n", | 71 "      --version               output version information and exit\n", | 
| 70           me.value().c_str()); | 72           me.value().c_str()); | 
| 71   ToolSupport::UsageTail(me); | 73   ToolSupport::UsageTail(me); | 
| 72 } | 74 } | 
| 73 | 75 | 
| 74 int HandlerMain(int argc, char* argv[]) { | 76 int HandlerMain(int argc, char* argv[]) { | 
| 75   const base::FilePath argv0( | 77   const base::FilePath argv0( | 
| 76       ToolSupport::CommandLineArgumentToFilePathStringType(argv[0])); | 78       ToolSupport::CommandLineArgumentToFilePathStringType(argv[0])); | 
| 77   const base::FilePath me(argv0.BaseName()); | 79   const base::FilePath me(argv0.BaseName()); | 
| 78 | 80 | 
| 79   enum OptionFlags { | 81   enum OptionFlags { | 
| 80     // Long options without short equivalents. | 82     // Long options without short equivalents. | 
| 81     kOptionLastChar = 255, | 83     kOptionLastChar = 255, | 
| 82     kOptionAnnotation, | 84     kOptionAnnotation, | 
| 83     kOptionDatabase, | 85     kOptionDatabase, | 
| 84 #if defined(OS_MACOSX) | 86 #if defined(OS_MACOSX) | 
| 85     kOptionHandshakeFD, | 87     kOptionHandshakeFD, | 
|  | 88     kOptionMachService, | 
| 86     kOptionResetOwnCrashExceptionPortToSystemDefault, | 89     kOptionResetOwnCrashExceptionPortToSystemDefault, | 
| 87 #elif defined(OS_WIN) | 90 #elif defined(OS_WIN) | 
| 88     kOptionPersistent, | 91     kOptionPersistent, | 
| 89     kOptionPipeName, | 92     kOptionPipeName, | 
| 90 #endif  // OS_MACOSX | 93 #endif  // OS_MACOSX | 
| 91     kOptionURL, | 94     kOptionURL, | 
| 92 | 95 | 
| 93     // Standard options. | 96     // Standard options. | 
| 94     kOptionHelp = -2, | 97     kOptionHelp = -2, | 
| 95     kOptionVersion = -3, | 98     kOptionVersion = -3, | 
| 96   }; | 99   }; | 
| 97 | 100 | 
| 98   struct { | 101   struct { | 
| 99     std::map<std::string, std::string> annotations; | 102     std::map<std::string, std::string> annotations; | 
| 100     std::string url; | 103     std::string url; | 
| 101     const char* database; | 104     const char* database; | 
| 102 #if defined(OS_MACOSX) | 105 #if defined(OS_MACOSX) | 
| 103     int handshake_fd; | 106     int handshake_fd; | 
|  | 107     std::string mach_service; | 
| 104     bool reset_own_crash_exception_port_to_system_default; | 108     bool reset_own_crash_exception_port_to_system_default; | 
| 105 #elif defined(OS_WIN) | 109 #elif defined(OS_WIN) | 
| 106     bool persistent; | 110     bool persistent; | 
| 107     std::string pipe_name; | 111     std::string pipe_name; | 
| 108 #endif  // OS_MACOSX | 112 #endif  // OS_MACOSX | 
| 109   } options = {}; | 113   } options = {}; | 
| 110 #if defined(OS_MACOSX) | 114 #if defined(OS_MACOSX) | 
| 111   options.handshake_fd = -1; | 115   options.handshake_fd = -1; | 
| 112   options.reset_own_crash_exception_port_to_system_default = false; | 116   options.reset_own_crash_exception_port_to_system_default = false; | 
| 113 #endif | 117 #endif | 
| 114 | 118 | 
| 115   const option long_options[] = { | 119   const option long_options[] = { | 
| 116       {"annotation", required_argument, nullptr, kOptionAnnotation}, | 120       {"annotation", required_argument, nullptr, kOptionAnnotation}, | 
| 117       {"database", required_argument, nullptr, kOptionDatabase}, | 121       {"database", required_argument, nullptr, kOptionDatabase}, | 
| 118 #if defined(OS_MACOSX) | 122 #if defined(OS_MACOSX) | 
| 119       {"handshake-fd", required_argument, nullptr, kOptionHandshakeFD}, | 123       {"handshake-fd", required_argument, nullptr, kOptionHandshakeFD}, | 
|  | 124       {"mach-service", required_argument, nullptr, kOptionMachService}, | 
| 120       {"reset-own-crash-exception-port-to-system-default", | 125       {"reset-own-crash-exception-port-to-system-default", | 
| 121        no_argument, | 126        no_argument, | 
| 122        nullptr, | 127        nullptr, | 
| 123        kOptionResetOwnCrashExceptionPortToSystemDefault}, | 128        kOptionResetOwnCrashExceptionPortToSystemDefault}, | 
| 124 #elif defined(OS_WIN) | 129 #elif defined(OS_WIN) | 
| 125       {"persistent", no_argument, nullptr, kOptionPersistent}, | 130       {"persistent", no_argument, nullptr, kOptionPersistent}, | 
| 126       {"pipe-name", required_argument, nullptr, kOptionPipeName}, | 131       {"pipe-name", required_argument, nullptr, kOptionPipeName}, | 
| 127 #endif  // OS_MACOSX | 132 #endif  // OS_MACOSX | 
| 128       {"url", required_argument, nullptr, kOptionURL}, | 133       {"url", required_argument, nullptr, kOptionURL}, | 
| 129       {"help", no_argument, nullptr, kOptionHelp}, | 134       {"help", no_argument, nullptr, kOptionHelp}, | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 155 #if defined(OS_MACOSX) | 160 #if defined(OS_MACOSX) | 
| 156       case kOptionHandshakeFD: { | 161       case kOptionHandshakeFD: { | 
| 157         if (!StringToNumber(optarg, &options.handshake_fd) || | 162         if (!StringToNumber(optarg, &options.handshake_fd) || | 
| 158             options.handshake_fd < 0) { | 163             options.handshake_fd < 0) { | 
| 159           ToolSupport::UsageHint(me, | 164           ToolSupport::UsageHint(me, | 
| 160                                  "--handshake-fd requires a file descriptor"); | 165                                  "--handshake-fd requires a file descriptor"); | 
| 161           return EXIT_FAILURE; | 166           return EXIT_FAILURE; | 
| 162         } | 167         } | 
| 163         break; | 168         break; | 
| 164       } | 169       } | 
|  | 170       case kOptionMachService: { | 
|  | 171         options.mach_service = optarg; | 
|  | 172         break; | 
|  | 173       } | 
| 165       case kOptionResetOwnCrashExceptionPortToSystemDefault: { | 174       case kOptionResetOwnCrashExceptionPortToSystemDefault: { | 
| 166         options.reset_own_crash_exception_port_to_system_default = true; | 175         options.reset_own_crash_exception_port_to_system_default = true; | 
| 167         break; | 176         break; | 
| 168       } | 177       } | 
| 169 #elif defined(OS_WIN) | 178 #elif defined(OS_WIN) | 
| 170       case kOptionPersistent: { | 179       case kOptionPersistent: { | 
| 171         options.persistent = true; | 180         options.persistent = true; | 
| 172         break; | 181         break; | 
| 173       } | 182       } | 
| 174       case kOptionPipeName: { | 183       case kOptionPipeName: { | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 191       default: { | 200       default: { | 
| 192         ToolSupport::UsageHint(me, nullptr); | 201         ToolSupport::UsageHint(me, nullptr); | 
| 193         return EXIT_FAILURE; | 202         return EXIT_FAILURE; | 
| 194       } | 203       } | 
| 195     } | 204     } | 
| 196   } | 205   } | 
| 197   argc -= optind; | 206   argc -= optind; | 
| 198   argv += optind; | 207   argv += optind; | 
| 199 | 208 | 
| 200 #if defined(OS_MACOSX) | 209 #if defined(OS_MACOSX) | 
| 201   if (options.handshake_fd < 0) { | 210   if (options.handshake_fd < 0 && options.mach_service.empty()) { | 
| 202     ToolSupport::UsageHint(me, "--handshake-fd is required"); | 211     ToolSupport::UsageHint(me, "--handshake-fd or --mach-service is required"); | 
|  | 212     return EXIT_FAILURE; | 
|  | 213   } | 
|  | 214   if (options.handshake_fd >= 0 && !options.mach_service.empty()) { | 
|  | 215     ToolSupport::UsageHint( | 
|  | 216         me, "--handshake-fd and --mach-service are incompatible"); | 
| 203     return EXIT_FAILURE; | 217     return EXIT_FAILURE; | 
| 204   } | 218   } | 
| 205 #elif defined(OS_WIN) | 219 #elif defined(OS_WIN) | 
| 206   if (options.pipe_name.empty()) { | 220   if (options.pipe_name.empty()) { | 
| 207     ToolSupport::UsageHint(me, "--pipe-name is required"); | 221     ToolSupport::UsageHint(me, "--pipe-name is required"); | 
| 208     return EXIT_FAILURE; | 222     return EXIT_FAILURE; | 
| 209   } | 223   } | 
| 210 #endif | 224 #endif | 
| 211 | 225 | 
| 212   if (!options.database) { | 226   if (!options.database) { | 
| 213     ToolSupport::UsageHint(me, "--database is required"); | 227     ToolSupport::UsageHint(me, "--database is required"); | 
| 214     return EXIT_FAILURE; | 228     return EXIT_FAILURE; | 
| 215   } | 229   } | 
| 216 | 230 | 
| 217   if (argc) { | 231   if (argc) { | 
| 218     ToolSupport::UsageHint(me, nullptr); | 232     ToolSupport::UsageHint(me, nullptr); | 
| 219     return EXIT_FAILURE; | 233     return EXIT_FAILURE; | 
| 220   } | 234   } | 
| 221 | 235 | 
| 222 #if defined(OS_MACOSX) | 236 #if defined(OS_MACOSX) | 
| 223   CloseStdinAndStdout(); | 237   if (options.mach_service.empty()) { | 
|  | 238     // Don’t do this when being run by launchd. See launchd.plist(5). | 
|  | 239     CloseStdinAndStdout(); | 
|  | 240   } | 
| 224 | 241 | 
| 225   if (options.reset_own_crash_exception_port_to_system_default) { | 242   if (options.reset_own_crash_exception_port_to_system_default) { | 
| 226     CrashpadClient::UseSystemDefaultHandler(); | 243     CrashpadClient::UseSystemDefaultHandler(); | 
| 227   } | 244   } | 
| 228 | 245 | 
| 229   base::mac::ScopedMachReceiveRight receive_right( | 246   base::mac::ScopedMachReceiveRight receive_right; | 
| 230       ChildPortHandshake::RunServerForFD( | 247 | 
| 231           base::ScopedFD(options.handshake_fd), | 248   if (options.handshake_fd >= 0) { | 
| 232           ChildPortHandshake::PortRightType::kReceiveRight)); | 249     receive_right.reset( | 
|  | 250         ChildPortHandshake::RunServerForFD( | 
|  | 251             base::ScopedFD(options.handshake_fd), | 
|  | 252             ChildPortHandshake::PortRightType::kReceiveRight)); | 
|  | 253   } else if (!options.mach_service.empty()) { | 
|  | 254     receive_right = BootstrapCheckIn(options.mach_service); | 
|  | 255   } | 
|  | 256 | 
| 233   if (!receive_right.is_valid()) { | 257   if (!receive_right.is_valid()) { | 
| 234     return EXIT_FAILURE; | 258     return EXIT_FAILURE; | 
| 235   } | 259   } | 
| 236 | 260 | 
| 237   ExceptionHandlerServer exception_handler_server(receive_right.Pass()); | 261   ExceptionHandlerServer exception_handler_server( | 
|  | 262       receive_right.Pass(), !options.mach_service.empty()); | 
| 238 #elif defined(OS_WIN) | 263 #elif defined(OS_WIN) | 
| 239   ExceptionHandlerServer exception_handler_server(options.pipe_name, | 264   ExceptionHandlerServer exception_handler_server(options.pipe_name, | 
| 240                                                   options.persistent); | 265                                                   options.persistent); | 
| 241 #endif  // OS_MACOSX | 266 #endif  // OS_MACOSX | 
| 242 | 267 | 
| 243   scoped_ptr<CrashReportDatabase> database(CrashReportDatabase::Initialize( | 268   scoped_ptr<CrashReportDatabase> database(CrashReportDatabase::Initialize( | 
| 244       base::FilePath(ToolSupport::CommandLineArgumentToFilePathStringType( | 269       base::FilePath(ToolSupport::CommandLineArgumentToFilePathStringType( | 
| 245           options.database)))); | 270           options.database)))); | 
| 246   if (!database) { | 271   if (!database) { | 
| 247     return EXIT_FAILURE; | 272     return EXIT_FAILURE; | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 265 | 290 | 
| 266 #if defined(OS_MACOSX) | 291 #if defined(OS_MACOSX) | 
| 267 int main(int argc, char* argv[]) { | 292 int main(int argc, char* argv[]) { | 
| 268   return crashpad::HandlerMain(argc, argv); | 293   return crashpad::HandlerMain(argc, argv); | 
| 269 } | 294 } | 
| 270 #elif defined(OS_WIN) | 295 #elif defined(OS_WIN) | 
| 271 int wmain(int argc, wchar_t* argv[]) { | 296 int wmain(int argc, wchar_t* argv[]) { | 
| 272   return crashpad::ToolSupport::Wmain(argc, argv, crashpad::HandlerMain); | 297   return crashpad::ToolSupport::Wmain(argc, argv, crashpad::HandlerMain); | 
| 273 } | 298 } | 
| 274 #endif  // OS_MACOSX | 299 #endif  // OS_MACOSX | 
| OLD | NEW | 
|---|