- // g_child_watch_add is necessary to prevent the process from becoming a
- // zombie.
- const base::ProcessId pid = base::GetProcId(handle);
- g_child_watch_add(pid,
- reinterpret_cast<GChildWatchFunc>(OnSetLayoutFinish),
- this);
- DVLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set << ": pid=" << pid;
+ PollUntilChildFinish(handle);
+
+ DVLOG(1) << "ExecuteSetLayoutCommand: "
+ << layout_to_set << ": pid=" << base::GetProcId(handle);
+}
+
+// Delay and loop until child process finishes and call the callback.
+void XKeyboardImpl::PollUntilChildFinish(const base::ProcessHandle handle) {
+ int exit_code;
+ DVLOG(1) << "PollUntilChildFinish: poll for pid=" << base::GetProcId(handle);
+ switch (base::GetTerminationStatus(handle, &exit_code)) {
+ case base::TERMINATION_STATUS_STILL_RUNNING:
+ DVLOG(1) << "PollUntilChildFinish: Try waiting again";
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&XKeyboardImpl::PollUntilChildFinish,
+ weak_factory_.GetWeakPtr(), handle),
+ base::TimeDelta::FromMilliseconds(kSetLayoutCommandCheckDelayMs));
+ return;
+
+ case base::TERMINATION_STATUS_NORMAL_TERMINATION:
+ DVLOG(1) << "PollUntilChildFinish: Child process finished";
+ OnSetLayoutFinish();
+ return;
+
+ case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
+ DVLOG(1) << "PollUntilChildFinish: Abnormal exit code: " << exit_code;
+ OnSetLayoutFinish();
+ return;
+
+ default:
+ NOTIMPLEMENTED();
+ OnSetLayoutFinish();
+ return;
+ }