Index: content/zygote/zygote_linux.cc |
diff --git a/content/zygote/zygote_linux.cc b/content/zygote/zygote_linux.cc |
index a5fb2038050c621f518a635e07203453ecf69c06..2ae6784c6a87005d915b2c3685338dc9c623f975 100644 |
--- a/content/zygote/zygote_linux.cc |
+++ b/content/zygote/zygote_linux.cc |
@@ -204,9 +204,11 @@ void Zygote::HandleReapRequest(int fd, |
void Zygote::HandleGetTerminationStatus(int fd, |
const Pickle& pickle, |
PickleIterator iter) { |
+ bool known_dead; |
base::ProcessHandle child; |
- if (!pickle.ReadInt(&iter, &child)) { |
+ if (!pickle.ReadBool(&iter, &known_dead) || |
+ !pickle.ReadInt(&iter, &child)) { |
LOG(WARNING) << "Error parsing GetTerminationStatus request " |
<< "from browser"; |
return; |
@@ -217,7 +219,20 @@ void Zygote::HandleGetTerminationStatus(int fd, |
if (UsingSUIDSandbox()) |
child = real_pids_to_sandbox_pids[child]; |
if (child) { |
- status = base::GetTerminationStatus(child, &exit_code); |
+ if (known_dead) { |
+ // If we know that the process is already dead and the kernel is cleaning |
+ // it up, we do want to wait until it becomes a zombie and not risk |
+ // returning eroneously that it is still running. However, we do not |
+ // want to risk a bug where we're told a process is dead when it's not. |
+ // By sending SIGKILL, we make sure that WaitForTerminationStatus will |
+ // return quickly even in this case. |
+ if (kill(child, SIGKILL)) { |
+ PLOG(ERROR) << "kill (" << child << ")"; |
+ } |
+ status = base::WaitForTerminationStatus(child, &exit_code); |
+ } else { |
+ status = base::GetTerminationStatus(child, &exit_code); |
+ } |
} else { |
// Assume that if we can't find the child in the sandbox, then |
// it terminated normally. |