Wait for process to exit before unmounting postinstall partition
When postinstall action is cancelled, update_engine sends SIGKILL to
postinstall scripts and immediately unmounts postinstall partition.
However, if the subprocess hasn't exited yet when we attempt to
unmount, there might be open file descriptors preventing the unmount
Test: th
Bug: 302336751
Change-Id: I2913957eb97a917e328609e801f8c1a944a5673b
diff --git a/common/subprocess.cc b/common/subprocess.cc
index a0cb9a7..9bd00d7 100644
--- a/common/subprocess.cc
+++ b/common/subprocess.cc
@@ -213,12 +213,21 @@
pid_record->second->callback.Reset();
// We don't care about output/return code, so we use SIGKILL here to ensure it
// will be killed, SIGTERM might lead to leaked subprocess.
- if (kill(pid, SIGKILL) != 0) {
- PLOG(WARNING) << "Error sending SIGKILL to " << pid;
+ CHECK_EQ(pid_record->second->proc.pid(), pid);
+ if (!pid_record->second->proc.Kill(SIGKILL, 5)) {
+ PLOG(WARNING) << "Error sending SIGKILL to "
+ << pid_record->second->proc.pid();
}
// Release the pid now so we don't try to kill it if Subprocess is destroyed
// before the corresponding ChildExitedCallback() is called.
pid_record->second->proc.Release();
+ if (subprocess_records_.count(pid)) {
+ siginfo_t info;
+ info.si_code = CLD_KILLED;
+ info.si_status = SIGKILL;
+ info.si_pid = pid;
+ ChildExitedCallback(info);
+ }
}
int Subprocess::GetPipeFd(pid_t pid, int fd) const {
diff --git a/common/subprocess_unittest.cc b/common/subprocess_unittest.cc
index ff4158e..8200e68 100644
--- a/common/subprocess_unittest.cc
+++ b/common/subprocess_unittest.cc
@@ -271,16 +271,20 @@
watcher_ = base::FileDescriptorWatcher::WatchReadable(
fifo_fd,
base::Bind(
- [](unique_ptr<base::FileDescriptorWatcher::Controller>* watcher,
+ [](brillo::BaseMessageLoop* loop,
+ unique_ptr<base::FileDescriptorWatcher::Controller>* watcher,
int fifo_fd,
uint32_t tag) {
- char c;
+ char c{};
EXPECT_EQ(1, HANDLE_EINTR(read(fifo_fd, &c, 1)));
EXPECT_EQ('X', c);
LOG(INFO) << "Killing tag " << tag;
Subprocess::Get().KillExec(tag);
+ loop->BreakLoop();
+ ASSERT_TRUE(Subprocess::Get().subprocess_records_.empty());
*watcher = nullptr;
},
+ &loop_,
// watcher_ is no longer used outside the clousure.
base::Unretained(&watcher_),
fifo_fd,