OLD | NEW |
| (Empty) |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "services/service_manager/embedder/main.h" | |
6 #include "base/allocator/features.h" | |
7 #include "base/command_line.h" | |
8 #include "base/debug/activity_tracker.h" | |
9 #include "base/logging.h" | |
10 #include "base/memory/ptr_util.h" | |
11 #include "base/process/memory.h" | |
12 #include "mojo/edk/embedder/embedder.h" | |
13 #include "services/service_manager/embedder/main_delegate.h" | |
14 #include "services/service_manager/embedder/set_process_title.h" | |
15 #include "services/service_manager/embedder/shared_file_util.h" | |
16 #include "services/service_manager/embedder/switches.h" | |
17 | |
18 #if defined(OS_WIN) | |
19 #include "base/win/process_startup_helper.h" | |
20 #include "ui/base/win/atl_module.h" | |
21 #endif | |
22 | |
23 #if defined(OS_POSIX) && !defined(OS_ANDROID) | |
24 #include <locale.h> | |
25 #include <signal.h> | |
26 | |
27 #include "base/file_descriptor_store.h" | |
28 #include "base/posix/global_descriptors.h" | |
29 #endif | |
30 | |
31 #if defined(OS_MACOSX) | |
32 #include "base/mac/scoped_nsautorelease_pool.h" | |
33 #include "services/service_manager/embedder/mac_init.h" | |
34 | |
35 #if BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) | |
36 #include "base/allocator/allocator_shim.h" | |
37 #endif | |
38 #endif // defined(OS_MACOSX) | |
39 | |
40 namespace service_manager { | |
41 | |
42 namespace { | |
43 | |
44 // Maximum message size allowed to be read from a Mojo message pipe in any | |
45 // service manager embedder process. | |
46 constexpr size_t kMaximumMojoMessageSize = 128 * 1024 * 1024; | |
47 | |
48 #if defined(OS_POSIX) && !defined(OS_ANDROID) | |
49 | |
50 // Setup signal-handling state: resanitize most signals, ignore SIGPIPE. | |
51 void SetupSignalHandlers() { | |
52 // Sanitise our signal handling state. Signals that were ignored by our | |
53 // parent will also be ignored by us. We also inherit our parent's sigmask. | |
54 sigset_t empty_signal_set; | |
55 CHECK_EQ(0, sigemptyset(&empty_signal_set)); | |
56 CHECK_EQ(0, sigprocmask(SIG_SETMASK, &empty_signal_set, NULL)); | |
57 | |
58 struct sigaction sigact; | |
59 memset(&sigact, 0, sizeof(sigact)); | |
60 sigact.sa_handler = SIG_DFL; | |
61 static const int signals_to_reset[] = { | |
62 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, | |
63 SIGALRM, SIGTERM, SIGCHLD, SIGBUS, SIGTRAP}; // SIGPIPE is set below. | |
64 for (unsigned i = 0; i < arraysize(signals_to_reset); i++) { | |
65 CHECK_EQ(0, sigaction(signals_to_reset[i], &sigact, NULL)); | |
66 } | |
67 | |
68 // Always ignore SIGPIPE. We check the return value of write(). | |
69 CHECK_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN)); | |
70 } | |
71 | |
72 void PopulateFDsFromCommandLine() { | |
73 const std::string& shared_file_param = | |
74 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
75 switches::kSharedFiles); | |
76 if (shared_file_param.empty()) | |
77 return; | |
78 | |
79 base::Optional<std::map<int, std::string>> shared_file_descriptors = | |
80 service_manager::ParseSharedFileSwitchValue(shared_file_param); | |
81 if (!shared_file_descriptors) | |
82 return; | |
83 | |
84 for (const auto& descriptor : *shared_file_descriptors) { | |
85 base::MemoryMappedFile::Region region; | |
86 const std::string& key = descriptor.second; | |
87 base::ScopedFD fd = base::GlobalDescriptors::GetInstance()->TakeFD( | |
88 descriptor.first, ®ion); | |
89 base::FileDescriptorStore::GetInstance().Set(key, std::move(fd), region); | |
90 } | |
91 } | |
92 | |
93 #endif // defined(OS_POSIX) && !defined(OS_ANDROID) | |
94 | |
95 } // namespace | |
96 | |
97 MainParams::MainParams(MainDelegate* delegate) : delegate(delegate) {} | |
98 | |
99 MainParams::~MainParams() {} | |
100 | |
101 int Main(const MainParams& params) { | |
102 MainDelegate* delegate = params.delegate; | |
103 DCHECK(delegate); | |
104 | |
105 #if defined(OS_MACOSX) && BUILDFLAG(USE_EXPERIMENTAL_ALLOCATOR_SHIM) | |
106 base::allocator::InitializeAllocatorShim(); | |
107 #endif | |
108 base::EnableTerminationOnOutOfMemory(); | |
109 | |
110 #if defined(OS_WIN) | |
111 base::win::RegisterInvalidParamHandler(); | |
112 ui::win::CreateATLModuleIfNeeded(); | |
113 #endif // defined(OS_WIN) | |
114 | |
115 // On Android setlocale() is not supported, and we don't override the signal | |
116 // handlers so we can get a stack trace when crashing. | |
117 #if defined(OS_POSIX) && !defined(OS_ANDROID) | |
118 // Set C library locale to make sure CommandLine can parse argument values in | |
119 // the correct encoding. | |
120 setlocale(LC_ALL, ""); | |
121 | |
122 SetupSignalHandlers(); | |
123 #endif | |
124 | |
125 #if !defined(OS_ANDROID) | |
126 // On Android, the command line is initialized when library is loaded. | |
127 int argc = 0; | |
128 const char** argv = nullptr; | |
129 | |
130 #if defined(OS_POSIX) | |
131 // argc/argv are ignored on Windows; see command_line.h for details. | |
132 argc = params.argc; | |
133 argv = params.argv; | |
134 #endif | |
135 | |
136 base::CommandLine::Init(argc, argv); | |
137 | |
138 #if defined(OS_POSIX) | |
139 PopulateFDsFromCommandLine(); | |
140 #endif | |
141 | |
142 base::EnableTerminationOnHeapCorruption(); | |
143 | |
144 #if defined(OS_WIN) | |
145 base::win::SetupCRT(*base::CommandLine::ForCurrentProcess()); | |
146 #endif | |
147 | |
148 SetProcessTitleFromCommandLine(argv); | |
149 #endif // !defined(OS_ANDROID) | |
150 | |
151 MainDelegate::InitializeParams init_params; | |
152 | |
153 #if defined(OS_MACOSX) | |
154 // We need this pool for all the objects created before we get to the event | |
155 // loop, but we don't want to leave them hanging around until the app quits. | |
156 // Each "main" needs to flush this pool right before it goes into its main | |
157 // event loop to get rid of the cruft. | |
158 std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool = | |
159 base::MakeUnique<base::mac::ScopedNSAutoreleasePool>(); | |
160 init_params.autorelease_pool = autorelease_pool.get(); | |
161 InitializeMac(); | |
162 #endif | |
163 | |
164 mojo::edk::SetMaxMessageSize(kMaximumMojoMessageSize); | |
165 mojo::edk::Init(); | |
166 | |
167 base::debug::GlobalActivityTracker* tracker = | |
168 base::debug::GlobalActivityTracker::Get(); | |
169 int exit_code = delegate->Initialize(init_params); | |
170 if (exit_code >= 0) { | |
171 if (tracker) { | |
172 tracker->SetProcessPhase( | |
173 base::debug::GlobalActivityTracker::PROCESS_LAUNCH_FAILED); | |
174 tracker->process_data().SetInt("exit-code", exit_code); | |
175 } | |
176 return exit_code; | |
177 } | |
178 | |
179 exit_code = delegate->Run(); | |
180 if (tracker) { | |
181 if (exit_code == 0) { | |
182 tracker->SetProcessPhaseIfEnabled( | |
183 base::debug::GlobalActivityTracker::PROCESS_EXITED_CLEANLY); | |
184 } else { | |
185 tracker->SetProcessPhaseIfEnabled( | |
186 base::debug::GlobalActivityTracker::PROCESS_EXITED_WITH_CODE); | |
187 tracker->process_data().SetInt("exit-code", exit_code); | |
188 } | |
189 } | |
190 | |
191 delegate->ShutDown(); | |
192 | |
193 return exit_code; | |
194 } | |
195 | |
196 } // namespace service_manager | |
OLD | NEW |