spawn_child_process.h
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 // Utility functions for spawning a helper process using a different 30 // CPU architecture. 31 32 #ifndef GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS 33 #define GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS 34 35 #include <AvailabilityMacros.h> 36 #ifndef MAC_OS_X_VERSION_10_6 37 #define MAC_OS_X_VERSION_10_6 1060 38 #endif 39 #include <crt_externs.h> 40 #include <mach-o/dyld.h> 41 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 42 #include <spawn.h> 43 #endif 44 45 #include <string> 46 #include <vector> 47 48 #include "google_breakpad/common/minidump_format.h" 49 50 namespace google_breakpad_test { 51 52 using std::string; 53 using std::vector; 54 55 const MDCPUArchitecture kNativeArchitecture = 56 #if defined(__i386__) 57 MD_CPU_ARCHITECTURE_X86 58 #elif defined(__x86_64__) 59 MD_CPU_ARCHITECTURE_AMD64 60 #elif defined(__ppc__) || defined(__ppc64__) 61 MD_CPU_ARCHITECTURE_PPC 62 #else 63 #error "This file has not been ported to this CPU architecture." 64 #endif 65 ; 66 67 const uint32_t kNativeContext = 68 #if defined(__i386__) 69 MD_CONTEXT_X86 70 #elif defined(__x86_64__) 71 MD_CONTEXT_AMD64 72 #elif defined(__ppc__) || defined(__ppc64__) 73 MD_CONTEXT_PPC 74 #else 75 #error "This file has not been ported to this CPU architecture." 76 #endif 77 ; 78 79 string GetExecutablePath() { 80 char self_path[PATH_MAX]; 81 uint32_t size = sizeof(self_path); 82 if (_NSGetExecutablePath(self_path, &size) != 0) 83 return ""; 84 return self_path; 85 } 86 87 string GetHelperPath() { 88 string helper_path(GetExecutablePath()); 89 size_t pos = helper_path.rfind('/'); 90 if (pos == string::npos) 91 return ""; 92 93 helper_path.erase(pos + 1); 94 helper_path += "minidump_generator_test_helper"; 95 return helper_path; 96 } 97 98 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 99 100 pid_t spawn_child_process(const char** argv) { 101 posix_spawnattr_t spawnattr; 102 if (posix_spawnattr_init(&spawnattr) != 0) 103 return (pid_t)-1; 104 105 cpu_type_t pref_cpu_types[2] = { 106 #if defined(__x86_64__) 107 CPU_TYPE_X86, 108 #elif defined(__i386__) 109 CPU_TYPE_X86_64, 110 #endif 111 CPU_TYPE_ANY 112 }; 113 114 // Set spawn attributes. 115 size_t attr_count = sizeof(pref_cpu_types) / sizeof(pref_cpu_types[0]); 116 size_t attr_ocount = 0; 117 if (posix_spawnattr_setbinpref_np(&spawnattr, 118 attr_count, 119 pref_cpu_types, 120 &attr_ocount) != 0 || 121 attr_ocount != attr_count) { 122 posix_spawnattr_destroy(&spawnattr); 123 return (pid_t)-1; 124 } 125 126 // Create an argv array. 127 vector<char*> argv_v; 128 while (*argv) { 129 argv_v.push_back(strdup(*argv)); 130 argv++; 131 } 132 argv_v.push_back(NULL); 133 pid_t new_pid = 0; 134 int result = posix_spawnp(&new_pid, argv_v[0], NULL, &spawnattr, 135 &argv_v[0], *_NSGetEnviron()); 136 posix_spawnattr_destroy(&spawnattr); 137 138 for (unsigned i = 0; i < argv_v.size(); i++) { 139 free(argv_v[i]); 140 } 141 142 return result == 0 ? new_pid : -1; 143 } 144 #endif 145 146 } // namespace google_breakpad_test 147 148 #endif // GOOGLE_BREAKPAD_CLIENT_MAC_TESTS_SPAWN_CHILD_PROCESS