OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/mach_broker_mac.h" | 5 #include "content/browser/mach_broker_mac.h" |
6 | 6 |
7 #include <bsm/libbsm.h> | 7 #include <bsm/libbsm.h> |
8 #include <servers/bootstrap.h> | 8 #include <servers/bootstrap.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 // unspoofable pid of the task that sent the message. | 108 // unspoofable pid of the task that sent the message. |
109 // | 109 // |
110 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). | 110 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). |
111 pid_t child_pid; | 111 pid_t child_pid; |
112 audit_token_to_au32(msg.trailer.msgh_audit, | 112 audit_token_to_au32(msg.trailer.msgh_audit, |
113 NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL); | 113 NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL); |
114 | 114 |
115 mach_port_t child_task_port = msg.child_task_port.name; | 115 mach_port_t child_task_port = msg.child_task_port.name; |
116 | 116 |
117 // Take the lock and update the broker information. | 117 // Take the lock and update the broker information. |
118 base::AutoLock lock(broker_->GetLock()); | 118 base::AutoLock lock(broker_->GetLock()); |
Mark Mentovai
2014/11/17 19:17:46
I would move this lock into FinalizePid(), replaci
sramajay
2014/11/18 14:15:19
I would take this suggestion as a new CL as it is
| |
119 broker_->FinalizePid(child_pid, child_task_port); | 119 broker_->FinalizePid(child_pid, child_task_port); |
120 } | 120 } |
121 | 121 |
122 MACH_LOG(ERROR, kr) << "mach_msg"; | 122 MACH_LOG(ERROR, kr) << "mach_msg"; |
123 } | 123 } |
124 | 124 |
125 private: | 125 private: |
126 // The MachBroker to use when new child task rights are received. Can be | 126 // The MachBroker to use when new child task rights are received. Can be |
127 // NULL. | 127 // NULL. |
128 MachBroker* broker_; // weak | 128 MachBroker* broker_; // weak |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 // Intentional leak. This thread is never joined or reaped. | 188 // Intentional leak. This thread is never joined or reaped. |
189 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this); | 189 MachListenerThreadDelegate* thread = new MachListenerThreadDelegate(this); |
190 if (thread->Init()) { | 190 if (thread->Init()) { |
191 base::PlatformThread::CreateNonJoinable(0, thread); | 191 base::PlatformThread::CreateNonJoinable(0, thread); |
192 } else { | 192 } else { |
193 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate"; | 193 LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate"; |
194 } | 194 } |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid) { | 198 void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid, |
199 int child_process_id) { | |
199 lock_.AssertAcquired(); | 200 lock_.AssertAcquired(); |
200 | 201 |
201 DCHECK_EQ(0u, mach_map_.count(pid)); | 202 DCHECK_EQ(0u, mach_map_.count(pid)); |
202 mach_map_[pid] = MACH_PORT_NULL; | 203 mach_map_[pid] = MACH_PORT_NULL; |
204 child_process_id_map_[child_process_id] = pid; | |
203 } | 205 } |
204 | 206 |
205 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { | 207 mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const { |
206 base::AutoLock lock(lock_); | 208 base::AutoLock lock(lock_); |
207 MachBroker::MachMap::const_iterator it = mach_map_.find(pid); | 209 MachBroker::MachMap::const_iterator it = mach_map_.find(pid); |
208 if (it == mach_map_.end()) | 210 if (it == mach_map_.end()) |
209 return MACH_PORT_NULL; | 211 return MACH_PORT_NULL; |
210 return it->second; | 212 return it->second; |
211 } | 213 } |
212 | 214 |
213 void MachBroker::BrowserChildProcessHostDisconnected( | 215 void MachBroker::BrowserChildProcessHostDisconnected( |
214 const ChildProcessData& data) { | 216 const ChildProcessData& data) { |
215 InvalidatePid(data.handle); | 217 InvalidateChildProcessId(data.id); |
216 } | 218 } |
217 | 219 |
218 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) { | 220 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) { |
219 InvalidatePid(data.handle); | 221 InvalidateChildProcessId(data.id); |
220 } | 222 } |
221 | 223 |
222 void MachBroker::Observe(int type, | 224 void MachBroker::Observe(int type, |
223 const NotificationSource& source, | 225 const NotificationSource& source, |
224 const NotificationDetails& details) { | 226 const NotificationDetails& details) { |
225 // TODO(rohitrao): These notifications do not always carry the proper PIDs, | |
226 // especially when the renderer is already gone or has crashed. Find a better | |
227 // way to listen for child process deaths. http://crbug.com/55734 | |
228 base::ProcessHandle handle = 0; | |
229 switch (type) { | 227 switch (type) { |
230 case NOTIFICATION_RENDERER_PROCESS_CLOSED: | 228 case NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
231 handle = Details<RenderProcessHost::RendererClosedDetails>( | 229 case NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
232 details)->handle; | 230 RenderProcessHost* host = Source<RenderProcessHost>(source).ptr(); |
231 InvalidateChildProcessId(host->GetID()); | |
233 break; | 232 break; |
234 case NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 233 } |
235 handle = Source<RenderProcessHost>(source)->GetHandle(); | |
236 break; | |
237 default: | 234 default: |
238 NOTREACHED() << "Unexpected notification"; | 235 NOTREACHED() << "Unexpected notification"; |
239 break; | 236 break; |
240 } | 237 } |
241 InvalidatePid(handle); | |
242 } | 238 } |
243 | 239 |
244 MachBroker::MachBroker() : listener_thread_started_(false) { | 240 MachBroker::MachBroker() : listener_thread_started_(false) { |
245 } | 241 } |
246 | 242 |
247 MachBroker::~MachBroker() {} | 243 MachBroker::~MachBroker() {} |
248 | 244 |
249 void MachBroker::FinalizePid(base::ProcessHandle pid, | 245 void MachBroker::FinalizePid(base::ProcessHandle pid, |
250 mach_port_t task_port) { | 246 mach_port_t task_port) { |
251 lock_.AssertAcquired(); | 247 lock_.AssertAcquired(); |
252 | 248 |
253 MachMap::iterator it = mach_map_.find(pid); | 249 MachMap::iterator it = mach_map_.find(pid); |
254 if (it == mach_map_.end()) { | 250 if (it == mach_map_.end()) { |
255 // Do nothing for unknown pids. | 251 // Do nothing for unknown pids. |
256 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; | 252 LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!"; |
257 return; | 253 return; |
258 } | 254 } |
259 | 255 |
260 DCHECK(it->second == MACH_PORT_NULL); | 256 DCHECK(it->second == MACH_PORT_NULL); |
261 if (it->second == MACH_PORT_NULL) | 257 if (it->second == MACH_PORT_NULL) |
262 it->second = task_port; | 258 it->second = task_port; |
263 } | 259 } |
264 | 260 |
265 void MachBroker::InvalidatePid(base::ProcessHandle pid) { | 261 void MachBroker::InvalidateChildProcessId(int child_process_id) { |
266 base::AutoLock lock(lock_); | 262 base::AutoLock lock(lock_); |
267 MachBroker::MachMap::iterator it = mach_map_.find(pid); | 263 MachBroker::ChildProcessIdMap::iterator it = |
268 if (it == mach_map_.end()) | 264 child_process_id_map_.find(child_process_id); |
Mark Mentovai
2014/11/17 19:17:46
Continuation lines get a 4-space indent, not a 2-s
sramajay
2014/11/18 14:15:19
Done.
| |
265 if (it == child_process_id_map_.end()) | |
269 return; | 266 return; |
270 | 267 |
268 base::ProcessHandle pid = it->second; | |
271 kern_return_t kr = mach_port_deallocate(mach_task_self(), | 269 kern_return_t kr = mach_port_deallocate(mach_task_self(), |
Mark Mentovai
2014/11/17 19:17:46
You should use mach_map_.find() and handle the cas
sramajay
2014/11/18 14:15:19
Done.
| |
272 it->second); | 270 mach_map_[pid]); |
273 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; | 271 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; |
274 mach_map_.erase(it); | 272 mach_map_.erase(pid); |
273 child_process_id_map_.erase(it); | |
275 } | 274 } |
276 | 275 |
277 // static | 276 // static |
278 std::string MachBroker::GetMachPortName() { | 277 std::string MachBroker::GetMachPortName() { |
279 const base::CommandLine* command_line = | 278 const base::CommandLine* command_line = |
280 base::CommandLine::ForCurrentProcess(); | 279 base::CommandLine::ForCurrentProcess(); |
281 const bool is_child = command_line->HasSwitch(switches::kProcessType); | 280 const bool is_child = command_line->HasSwitch(switches::kProcessType); |
282 | 281 |
283 // In non-browser (child) processes, use the parent's pid. | 282 // In non-browser (child) processes, use the parent's pid. |
284 const pid_t pid = is_child ? getppid() : getpid(); | 283 const pid_t pid = is_child ? getppid() : getpid(); |
285 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); | 284 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); |
286 } | 285 } |
287 | 286 |
288 void MachBroker::RegisterNotifications() { | 287 void MachBroker::RegisterNotifications() { |
289 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, | 288 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, |
290 NotificationService::AllBrowserContextsAndSources()); | 289 NotificationService::AllBrowserContextsAndSources()); |
291 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 290 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
292 NotificationService::AllBrowserContextsAndSources()); | 291 NotificationService::AllBrowserContextsAndSources()); |
293 | 292 |
294 // No corresponding StopObservingBrowserChildProcesses, | 293 // No corresponding StopObservingBrowserChildProcesses, |
295 // we leak this singleton. | 294 // we leak this singleton. |
296 BrowserChildProcessObserver::Add(this); | 295 BrowserChildProcessObserver::Add(this); |
297 } | 296 } |
298 | 297 |
299 } // namespace content | 298 } // namespace content |
OLD | NEW |