Skip to content

Commit 2380681

Browse files
Merge pull request #152 from redpanda-data/mboquard/core-8181/waitpid-workaround
reactor: Always retry waitpid
2 parents f212c77 + 09b0746 commit 2380681

File tree

2 files changed

+31
-32
lines changed

2 files changed

+31
-32
lines changed

include/seastar/core/reactor.hh

+1
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ private:
642642
void add_timer(timer<manual_clock>*) noexcept;
643643
bool queue_timer(timer<manual_clock>*) noexcept;
644644
void del_timer(timer<manual_clock>*) noexcept;
645+
future<int> do_waitpid(pid_t pid);
645646

646647
future<> run_exit_tasks();
647648
void stop();

src/core/reactor.cc

+30-32
Original file line numberDiff line numberDiff line change
@@ -2296,6 +2296,32 @@ static auto next_waitpid_timeout(std::chrono::milliseconds this_timeout) {
22962296

22972297
#endif
22982298

2299+
future<int> reactor::do_waitpid(pid_t pid) {
2300+
return do_with(int{}, std::chrono::milliseconds(0), [pid, this](int& wstatus,
2301+
std::chrono::milliseconds& wait_timeout) {
2302+
return repeat_until_value([this,
2303+
pid,
2304+
&wstatus,
2305+
&wait_timeout] {
2306+
return _thread_pool->submit<syscall_result<pid_t>>([pid, &wstatus] {
2307+
return wrap_syscall<pid_t>(::waitpid(pid, &wstatus, WNOHANG));
2308+
}).then([&wstatus, &wait_timeout](syscall_result<pid_t> ret) mutable {
2309+
if (ret.result == 0) {
2310+
wait_timeout = next_waitpid_timeout(wait_timeout);
2311+
return ::seastar::sleep(wait_timeout).then([] {
2312+
return make_ready_future<std::optional<int>>();
2313+
});
2314+
} else if (ret.result > 0) {
2315+
return make_ready_future<std::optional<int>>(wstatus);
2316+
} else {
2317+
ret.throw_if_error();
2318+
return make_ready_future<std::optional<int>>(-1);
2319+
}
2320+
});
2321+
});
2322+
});
2323+
}
2324+
22992325
future<int> reactor::waitpid(pid_t pid) {
23002326
return _thread_pool->submit<syscall_result<int>>([pid] {
23012327
return wrap_syscall<int>(syscall(__NR_pidfd_open, pid, O_NONBLOCK));
@@ -2304,39 +2330,11 @@ future<int> reactor::waitpid(pid_t pid) {
23042330
// pidfd_open() was introduced in linux 5.3, so the pidfd.error could be ENOSYS on
23052331
// older kernels. But it could be other error like EMFILE or ENFILE. anyway, we
23062332
// should always waitpid().
2307-
return do_with(int{}, std::chrono::milliseconds(0), [pid, this](int& wstatus,
2308-
std::chrono::milliseconds& wait_timeout) {
2309-
return repeat_until_value([this,
2310-
pid,
2311-
&wstatus,
2312-
&wait_timeout] {
2313-
return _thread_pool->submit<syscall_result<pid_t>>([pid, &wstatus] {
2314-
return wrap_syscall<pid_t>(::waitpid(pid, &wstatus, WNOHANG));
2315-
}).then([&wstatus, &wait_timeout] (syscall_result<pid_t> ret) mutable {
2316-
if (ret.result == 0) {
2317-
wait_timeout = next_waitpid_timeout(wait_timeout);
2318-
return ::seastar::sleep(wait_timeout).then([] {
2319-
return make_ready_future<std::optional<int>>();
2320-
});
2321-
} else if (ret.result > 0) {
2322-
return make_ready_future<std::optional<int>>(wstatus);
2323-
} else {
2324-
ret.throw_if_error();
2325-
return make_ready_future<std::optional<int>>(-1);
2326-
}
2327-
});
2328-
});
2329-
});
2333+
return do_waitpid(pid);
23302334
} else {
2331-
return do_with(pollable_fd(file_desc::from_fd(pidfd.result)), int{}, [pid, this](auto& pidfd, int& wstatus) {
2332-
return pidfd.readable().then([pid, &wstatus, this] {
2333-
return _thread_pool->submit<syscall_result<pid_t>>([pid, &wstatus] {
2334-
return wrap_syscall<pid_t>(::waitpid(pid, &wstatus, WNOHANG));
2335-
});
2336-
}).then([&wstatus] (syscall_result<pid_t> ret) {
2337-
ret.throw_if_error();
2338-
assert(ret.result > 0);
2339-
return make_ready_future<int>(wstatus);
2335+
return do_with(pollable_fd(file_desc::from_fd(pidfd.result)), [pid, this](auto& pidfd) {
2336+
return pidfd.readable().then([pid, this] {
2337+
return do_waitpid(pid);
23402338
});
23412339
});
23422340
}

0 commit comments

Comments
 (0)