| 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/browser_child_process_host.h" | 5 #include "content/browser/browser_child_process_host.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_path.h" | 8 #include "base/file_path.h" |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 } | 53 } |
| 54 | 54 |
| 55 private: | 55 private: |
| 56 int notification_type_; | 56 int notification_type_; |
| 57 ChildProcessInfo info_; | 57 ChildProcessInfo info_; |
| 58 }; | 58 }; |
| 59 | 59 |
| 60 } // namespace | 60 } // namespace |
| 61 | 61 |
| 62 BrowserChildProcessHost::BrowserChildProcessHost( | 62 BrowserChildProcessHost::BrowserChildProcessHost( |
| 63 ChildProcessInfo::ProcessType type) | 63 content::ProcessType type) |
| 64 : ChildProcessInfo(type, -1), | 64 : ChildProcessInfo(type, -1), |
| 65 ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)), | 65 ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)), |
| 66 #if !defined(OS_WIN) | 66 #if !defined(OS_WIN) |
| 67 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), | 67 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), |
| 68 #endif | 68 #endif |
| 69 disconnect_was_alive_(false) { | 69 disconnect_was_alive_(false) { |
| 70 AddFilter(new TraceMessageFilter); | 70 AddFilter(new TraceMessageFilter); |
| 71 | 71 |
| 72 g_child_process_list.Get().push_back(this); | 72 g_child_process_list.Get().push_back(this); |
| 73 } | 73 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 DCHECK(handle() != base::kNullProcessHandle); | 150 DCHECK(handle() != base::kNullProcessHandle); |
| 151 int exit_code; | 151 int exit_code; |
| 152 base::TerminationStatus status = GetChildTerminationStatus(&exit_code); | 152 base::TerminationStatus status = GetChildTerminationStatus(&exit_code); |
| 153 switch (status) { | 153 switch (status) { |
| 154 case base::TERMINATION_STATUS_PROCESS_CRASHED: | 154 case base::TERMINATION_STATUS_PROCESS_CRASHED: |
| 155 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: { | 155 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: { |
| 156 OnProcessCrashed(exit_code); | 156 OnProcessCrashed(exit_code); |
| 157 // Report that this child process crashed. | 157 // Report that this child process crashed. |
| 158 Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED); | 158 Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED); |
| 159 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed", | 159 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Crashed", |
| 160 this->type(), MAX_PROCESS); | 160 this->type(), |
| 161 content::PROCESS_TYPE_MAX); |
| 161 if (disconnect_was_alive_) { | 162 if (disconnect_was_alive_) { |
| 162 UMA_HISTOGRAM_ENUMERATION("ChildProcess.CrashedWasAlive", | 163 UMA_HISTOGRAM_ENUMERATION("ChildProcess.CrashedWasAlive", |
| 163 this->type(), MAX_PROCESS); | 164 this->type(), |
| 165 content::PROCESS_TYPE_MAX); |
| 164 } | 166 } |
| 165 break; | 167 break; |
| 166 } | 168 } |
| 167 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: { | 169 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: { |
| 168 OnProcessWasKilled(exit_code); | 170 OnProcessWasKilled(exit_code); |
| 169 // Report that this child process was killed. | 171 // Report that this child process was killed. |
| 170 Notify(content::NOTIFICATION_CHILD_PROCESS_WAS_KILLED); | 172 Notify(content::NOTIFICATION_CHILD_PROCESS_WAS_KILLED); |
| 171 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed", | 173 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Killed", |
| 172 this->type(), MAX_PROCESS); | 174 this->type(), |
| 175 content::PROCESS_TYPE_MAX); |
| 173 if (disconnect_was_alive_) { | 176 if (disconnect_was_alive_) { |
| 174 UMA_HISTOGRAM_ENUMERATION("ChildProcess.KilledWasAlive", | 177 UMA_HISTOGRAM_ENUMERATION("ChildProcess.KilledWasAlive", |
| 175 this->type(), MAX_PROCESS); | 178 this->type(), |
| 179 content::PROCESS_TYPE_MAX); |
| 176 } | 180 } |
| 177 break; | 181 break; |
| 178 } | 182 } |
| 179 case base::TERMINATION_STATUS_STILL_RUNNING: { | 183 case base::TERMINATION_STATUS_STILL_RUNNING: { |
| 180 // Exit code not yet available. Ensure we don't wait forever for an exit | 184 // Exit code not yet available. Ensure we don't wait forever for an exit |
| 181 // code. | 185 // code. |
| 182 if (disconnect_was_alive_) { | 186 if (disconnect_was_alive_) { |
| 183 UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive", | 187 UMA_HISTOGRAM_ENUMERATION("ChildProcess.DisconnectedAlive", |
| 184 this->type(), MAX_PROCESS); | 188 this->type(), |
| 189 content::PROCESS_TYPE_MAX); |
| 185 break; | 190 break; |
| 186 } | 191 } |
| 187 disconnect_was_alive_ = true; | 192 disconnect_was_alive_ = true; |
| 188 #if defined(OS_WIN) | 193 #if defined(OS_WIN) |
| 189 child_watcher_.StartWatching(new base::WaitableEvent(handle()), this); | 194 child_watcher_.StartWatching(new base::WaitableEvent(handle()), this); |
| 190 #else | 195 #else |
| 191 // On non-Windows platforms, give the child process some time to die after | 196 // On non-Windows platforms, give the child process some time to die after |
| 192 // disconnecting the channel so that the exit code and termination status | 197 // disconnecting the channel so that the exit code and termination status |
| 193 // become available. This is best effort -- if the process doesn't die | 198 // become available. This is best effort -- if the process doesn't die |
| 194 // within the time limit, this object gets destroyed. | 199 // within the time limit, this object gets destroyed. |
| 195 const int kExitCodeWaitMs = 250; | 200 const int kExitCodeWaitMs = 250; |
| 196 MessageLoop::current()->PostDelayedTask( | 201 MessageLoop::current()->PostDelayedTask( |
| 197 FROM_HERE, | 202 FROM_HERE, |
| 198 base::Bind(&BrowserChildProcessHost::OnChildDisconnected, | 203 base::Bind(&BrowserChildProcessHost::OnChildDisconnected, |
| 199 task_factory_.GetWeakPtr()), | 204 task_factory_.GetWeakPtr()), |
| 200 kExitCodeWaitMs); | 205 kExitCodeWaitMs); |
| 201 #endif | 206 #endif |
| 202 return; | 207 return; |
| 203 } | 208 } |
| 204 | 209 |
| 205 default: | 210 default: |
| 206 break; | 211 break; |
| 207 } | 212 } |
| 208 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected", | 213 UMA_HISTOGRAM_ENUMERATION("ChildProcess.Disconnected", |
| 209 this->type(), MAX_PROCESS); | 214 this->type(), |
| 215 content::PROCESS_TYPE_MAX); |
| 210 // Notify in the main loop of the disconnection. | 216 // Notify in the main loop of the disconnection. |
| 211 Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED); | 217 Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED); |
| 212 OnChildDied(); | 218 OnChildDied(); |
| 213 } | 219 } |
| 214 | 220 |
| 215 // The child process handle has been signaled so the exit code is finally | 221 // The child process handle has been signaled so the exit code is finally |
| 216 // available. Unfortunately STILL_ACTIVE (0x103) is a valid exit code in | 222 // available. Unfortunately STILL_ACTIVE (0x103) is a valid exit code in |
| 217 // which case we should not call OnChildDisconnected() or else we will be | 223 // which case we should not call OnChildDisconnected() or else we will be |
| 218 // waiting forever. | 224 // waiting forever. |
| 219 void BrowserChildProcessHost::OnWaitableEventSignaled( | 225 void BrowserChildProcessHost::OnWaitableEventSignaled( |
| (...skipping 21 matching lines...) Expand all Loading... |
| 241 void BrowserChildProcessHost::ClientHook::OnProcessLaunched() { | 247 void BrowserChildProcessHost::ClientHook::OnProcessLaunched() { |
| 242 if (!host_->child_process_->GetHandle()) { | 248 if (!host_->child_process_->GetHandle()) { |
| 243 host_->OnChildDied(); | 249 host_->OnChildDied(); |
| 244 return; | 250 return; |
| 245 } | 251 } |
| 246 host_->set_handle(host_->child_process_->GetHandle()); | 252 host_->set_handle(host_->child_process_->GetHandle()); |
| 247 host_->OnProcessLaunched(); | 253 host_->OnProcessLaunched(); |
| 248 } | 254 } |
| 249 | 255 |
| 250 BrowserChildProcessHost::Iterator::Iterator() | 256 BrowserChildProcessHost::Iterator::Iterator() |
| 251 : all_(true), type_(UNKNOWN_PROCESS) { | 257 : all_(true), type_(content::PROCESS_TYPE_UNKNOWN) { |
| 252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << | 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << |
| 253 "ChildProcessInfo::Iterator must be used on the IO thread."; | 259 "ChildProcessInfo::Iterator must be used on the IO thread."; |
| 254 iterator_ = g_child_process_list.Get().begin(); | 260 iterator_ = g_child_process_list.Get().begin(); |
| 255 } | 261 } |
| 256 | 262 |
| 257 BrowserChildProcessHost::Iterator::Iterator(ChildProcessInfo::ProcessType type) | 263 BrowserChildProcessHost::Iterator::Iterator(content::ProcessType type) |
| 258 : all_(false), type_(type) { | 264 : all_(false), type_(type) { |
| 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << | 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << |
| 260 "ChildProcessInfo::Iterator must be used on the IO thread."; | 266 "ChildProcessInfo::Iterator must be used on the IO thread."; |
| 261 iterator_ = g_child_process_list.Get().begin(); | 267 iterator_ = g_child_process_list.Get().begin(); |
| 262 if (!Done() && (*iterator_)->type() != type_) | 268 if (!Done() && (*iterator_)->type() != type_) |
| 263 ++(*this); | 269 ++(*this); |
| 264 } | 270 } |
| 265 | 271 |
| 266 BrowserChildProcessHost* BrowserChildProcessHost::Iterator::operator++() { | 272 BrowserChildProcessHost* BrowserChildProcessHost::Iterator::operator++() { |
| 267 do { | 273 do { |
| 268 ++iterator_; | 274 ++iterator_; |
| 269 if (Done()) | 275 if (Done()) |
| 270 break; | 276 break; |
| 271 | 277 |
| 272 if (!all_ && (*iterator_)->type() != type_) | 278 if (!all_ && (*iterator_)->type() != type_) |
| 273 continue; | 279 continue; |
| 274 | 280 |
| 275 return *iterator_; | 281 return *iterator_; |
| 276 } while (true); | 282 } while (true); |
| 277 | 283 |
| 278 return NULL; | 284 return NULL; |
| 279 } | 285 } |
| 280 | 286 |
| 281 bool BrowserChildProcessHost::Iterator::Done() { | 287 bool BrowserChildProcessHost::Iterator::Done() { |
| 282 return iterator_ == g_child_process_list.Get().end(); | 288 return iterator_ == g_child_process_list.Get().end(); |
| 283 } | 289 } |
| OLD | NEW |