Skip to content

Commit 4d1c44a

Browse files
committed
[sshfs] Use Timer and wrap posix signals
1 parent a3e240e commit 4d1c44a

File tree

2 files changed

+49
-26
lines changed

2 files changed

+49
-26
lines changed

include/multipass/platform_unix.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,25 @@
2222

2323
#include <signal.h>
2424

25-
namespace multipass
25+
#include "singleton.h"
26+
27+
#define MP_POSIX_SIGNAL multipass::platform::SignalWrapper::instance()
28+
29+
namespace multipass::platform
2630
{
27-
namespace platform
31+
32+
class SignalWrapper : public Singleton<SignalWrapper>
2833
{
34+
public:
35+
SignalWrapper(const PrivatePass&) noexcept;
36+
37+
virtual int mask_signals(int how, const sigset_t* sigset, sigset_t* old_set = nullptr) const;
38+
virtual int send(pthread_t target, int signal) const;
39+
virtual int wait(const sigset_t& sigset, int& got) const;
40+
};
41+
2942
sigset_t make_sigset(const std::vector<int>& sigs);
3043
sigset_t make_and_block_signals(const std::vector<int>& sigs);
31-
} // namespace platform
32-
}
44+
45+
} // namespace multipass::platform
3346
#endif // MULTIPASS_PLATFORM_UNIX_H

src/platform/platform_unix.cpp

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include <unistd.h>
2626

2727
#include <libssh/sftp.h>
28-
#include <multipass/auto_join_thread.h>
28+
#include <multipass/timer.h>
2929

3030
namespace mp = multipass;
3131

@@ -158,6 +158,25 @@ int mp::platform::symlink_attr_from(const char* path, sftp_attributes_struct* at
158158
return 0;
159159
}
160160

161+
mp::platform::SignalWrapper::SignalWrapper(const PrivatePass& pass) noexcept
162+
: Singleton(pass){}
163+
164+
165+
int mp::platform::SignalWrapper::mask_signals(int how, const sigset_t* sigset, sigset_t* old_set) const
166+
{
167+
return pthread_sigmask(how, sigset, old_set);
168+
}
169+
170+
int mp::platform::SignalWrapper::send(pthread_t target, int signal) const
171+
{
172+
return pthread_kill(target, signal);
173+
}
174+
175+
int mp::platform::SignalWrapper::wait(const sigset_t& sigset, int& got) const
176+
{
177+
return sigwait(std::addressof(sigset), std::addressof(got));
178+
}
179+
161180
sigset_t mp::platform::make_sigset(const std::vector<int>& sigs)
162181
{
163182
sigset_t sigset;
@@ -172,7 +191,7 @@ sigset_t mp::platform::make_sigset(const std::vector<int>& sigs)
172191
sigset_t mp::platform::make_and_block_signals(const std::vector<int>& sigs)
173192
{
174193
auto sigset{make_sigset(sigs)};
175-
pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
194+
MP_POSIX_SIGNAL.mask_signals(SIG_BLOCK, &sigset, nullptr);
176195
return sigset;
177196
}
178197

@@ -188,34 +207,25 @@ std::function<std::optional<int>(const std::function<bool()>&)> mp::platform::ma
188207
{
189208
return [sigset = make_and_block_signals({SIGQUIT, SIGTERM, SIGHUP, SIGUSR2}),
190209
period](const std::function<bool()>& condition) -> std::optional<int> {
191-
std::mutex sig_mtx;
192-
std::condition_variable sig_cv;
193-
int sig = SIGUSR2;
194-
195-
// A signal generator that triggers after `timeout`
196-
AutoJoinThread signaler([&sig_mtx, &sig_cv, &sig, &period, signalee = pthread_self()] {
197-
std::unique_lock lock(sig_mtx);
198-
while (!sig_cv.wait_for(lock, period, [&sig] { return sig != SIGUSR2; }))
199-
{
200-
pthread_kill(signalee, SIGUSR2);
201-
}
202-
});
210+
211+
// create a timer to periodically send SIGUSR2
212+
utils::Timer signal_generator{period, [signalee = pthread_self()] {
213+
MP_POSIX_SIGNAL.send(signalee, SIGUSR2);
214+
}};
203215

204216
// wait on signals and condition
205217
int latest_signal = SIGUSR2;
206218
while (latest_signal == SIGUSR2 && condition())
207219
{
220+
signal_generator.start();
221+
208222
// can't use sigtimedwait since macOS doesn't support it
209-
sigwait(&sigset, &latest_signal);
223+
MP_POSIX_SIGNAL.wait(sigset, latest_signal);
210224
}
211225

212-
{ // set `sig` to something other than SIGUSR2 so `signaler` knows to exit
213-
std::lock_guard lock(sig_mtx);
214-
sig = latest_signal == SIGUSR2 ? 0 : latest_signal;
215-
}
216-
sig_cv.notify_all();
226+
signal_generator.stop();
217227

218-
// if `sig` is 0 then we know we're exiting because condition() was false
219-
return sig ? std::make_optional(sig) : std::nullopt;
228+
// if `latest_signal` is SIGUSR2 then we know `condition()` is false
229+
return latest_signal == SIGUSR2 ? std::nullopt : std::make_optional(latest_signal);
220230
};
221231
}

0 commit comments

Comments
 (0)