Chromium Code Reviews| 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 177 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_[pid] = child_process_id; | |
| 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 InvalidatePid(data.handle); |
|
Mark Mentovai
2014/11/13 14:00:10
Why don’t you get rid of InvalidatePid and use Inv
sramajay
2014/11/13 15:45:28
Acknowledged.
| |
| 216 } | 218 } |
| 217 | 219 |
| 218 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) { | 220 void MachBroker::BrowserChildProcessCrashed(const ChildProcessData& data) { |
| 219 InvalidatePid(data.handle); | 221 InvalidatePid(data.handle); |
| 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(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 265 void MachBroker::InvalidatePid(base::ProcessHandle pid) { | 261 void MachBroker::InvalidatePid(base::ProcessHandle pid) { |
| 266 base::AutoLock lock(lock_); | 262 base::AutoLock lock(lock_); |
| 267 MachBroker::MachMap::iterator it = mach_map_.find(pid); | 263 MachBroker::MachMap::iterator it = mach_map_.find(pid); |
| 268 if (it == mach_map_.end()) | 264 if (it == mach_map_.end()) |
| 269 return; | 265 return; |
| 270 | 266 |
| 271 kern_return_t kr = mach_port_deallocate(mach_task_self(), | 267 kern_return_t kr = mach_port_deallocate(mach_task_self(), |
| 272 it->second); | 268 it->second); |
| 273 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; | 269 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; |
| 274 mach_map_.erase(it); | 270 mach_map_.erase(it); |
| 271 child_process_id_map_.erase(pid); | |
| 275 } | 272 } |
| 276 | 273 |
| 274 void MachBroker::InvalidateChildProcessId(int child_process_id) { | |
| 275 base::ProcessHandle pid = 0; | |
| 276 for (const auto& it : child_process_id_map_) { | |
|
Mark Mentovai
2014/11/13 14:00:10
You need to assert that the lock is held to be abl
sramajay
2014/11/13 15:45:28
Ok. I can remove the InvalidatePid with the above
| |
| 277 if (it.second == child_process_id) { | |
|
Mark Mentovai
2014/11/13 14:00:10
It seems like you really want a bidirectional map,
sramajay
2014/11/13 15:45:28
Its not only InvalidatePid(), but FinalizePid() is
Mark Mentovai
2014/11/13 16:04:53
Then it sounds like we should have a map from PID
| |
| 278 pid = it.first; | |
| 279 break; | |
| 280 } | |
| 281 } | |
| 282 if (pid) | |
| 283 InvalidatePid(pid); | |
| 284 } | |
| 285 | |
| 286 | |
| 277 // static | 287 // static |
| 278 std::string MachBroker::GetMachPortName() { | 288 std::string MachBroker::GetMachPortName() { |
| 279 const base::CommandLine* command_line = | 289 const base::CommandLine* command_line = |
| 280 base::CommandLine::ForCurrentProcess(); | 290 base::CommandLine::ForCurrentProcess(); |
| 281 const bool is_child = command_line->HasSwitch(switches::kProcessType); | 291 const bool is_child = command_line->HasSwitch(switches::kProcessType); |
| 282 | 292 |
| 283 // In non-browser (child) processes, use the parent's pid. | 293 // In non-browser (child) processes, use the parent's pid. |
| 284 const pid_t pid = is_child ? getppid() : getpid(); | 294 const pid_t pid = is_child ? getppid() : getpid(); |
| 285 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); | 295 return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid); |
| 286 } | 296 } |
| 287 | 297 |
| 288 void MachBroker::RegisterNotifications() { | 298 void MachBroker::RegisterNotifications() { |
| 289 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, | 299 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 290 NotificationService::AllBrowserContextsAndSources()); | 300 NotificationService::AllBrowserContextsAndSources()); |
| 291 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 301 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 292 NotificationService::AllBrowserContextsAndSources()); | 302 NotificationService::AllBrowserContextsAndSources()); |
| 293 | 303 |
| 294 // No corresponding StopObservingBrowserChildProcesses, | 304 // No corresponding StopObservingBrowserChildProcesses, |
| 295 // we leak this singleton. | 305 // we leak this singleton. |
| 296 BrowserChildProcessObserver::Add(this); | 306 BrowserChildProcessObserver::Add(this); |
| 297 } | 307 } |
| 298 | 308 |
| 299 } // namespace content | 309 } // namespace content |
| OLD | NEW |