Skip to content

Commit 16562f3

Browse files
committed
[sshfs] Change watchdog to not use sigtimedwait
1 parent 95343c0 commit 16562f3

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

src/platform/platform_unix.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <multipass/utils.h>
2121

2222
#include <grp.h>
23+
#include <scope_guard.hpp>
2324
#include <sys/stat.h>
2425
#include <sys/time.h>
2526
#include <unistd.h>
@@ -185,14 +186,34 @@ timespec make_timespec(std::chrono::duration<Rep, Period> duration)
185186
std::function<std::optional<int>(const std::function<bool()>&)> mp::platform::make_quit_watchdog(
186187
const std::chrono::milliseconds& timeout)
187188
{
188-
return [sigset = make_and_block_signals({SIGQUIT, SIGTERM, SIGHUP}),
189+
return [sigset = make_and_block_signals({SIGQUIT, SIGTERM, SIGHUP, SIGUSR2}),
189190
time = make_timespec(timeout)](const std::function<bool()>& condition) -> std::optional<int> {
190-
while (condition())
191+
// create a timer to send SIGUSR2 which unblocks this thread
192+
sigevent sevp{};
193+
sevp.sigev_notify = SIGEV_SIGNAL;
194+
sevp.sigev_signo = SIGUSR2;
195+
196+
timer_t timer{};
197+
if (timer_create(CLOCK_MONOTONIC, &sevp, &timer) == -1)
198+
throw std::runtime_error(fmt::format("Could not create timer: {}", strerror(errno)));
199+
200+
// scope guard to make sure the timer is deleted once it's no longer needed
201+
const auto timer_guard = sg::make_scope_guard([timer]() noexcept { timer_delete(timer); });
202+
203+
// set timer interval and initial time to provided timeout
204+
const itimerspec timer_interval{time, time};
205+
if (timer_settime(timer, 0, &timer_interval, nullptr) == -1)
206+
throw std::runtime_error(fmt::format("Could not set timer: {}", strerror(errno)));
207+
208+
// wait on signals and condition
209+
int sig = SIGUSR2;
210+
while (sig == SIGUSR2 && condition())
191211
{
192-
if (const int sig = sigtimedwait(&sigset, nullptr, &time); sig != -1)
193-
return sig;
212+
// can't use sigtimedwait since macOS doesn't support it
213+
sigwait(&sigset, &sig);
194214
}
195215

196-
return std::nullopt;
216+
// if sig is SIGUSR2 then we know we're exiting because condition() was false
217+
return sig == SIGUSR2 ? std::nullopt : std::make_optional(sig);
197218
};
198219
}

0 commit comments

Comments
 (0)