Skip to content

Commit

Permalink
[sshfs] Use seperate signaling thread
Browse files Browse the repository at this point in the history
  • Loading branch information
Sploder12 committed Dec 6, 2024
1 parent 3df817f commit 979ee07
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 20 deletions.
48 changes: 29 additions & 19 deletions src/platform/platform_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <unistd.h>

#include <libssh/sftp.h>
#include <multipass/auto_join_thread.h>

namespace mp = multipass;

Expand Down Expand Up @@ -183,37 +184,46 @@ timespec make_timespec(std::chrono::duration<Rep, Period> duration)
return timespec{seconds.count(), std::chrono::duration_cast<std::chrono::nanoseconds>(duration - seconds).count()};
}

#include <iostream>

std::function<std::optional<int>(const std::function<bool()>&)> mp::platform::make_quit_watchdog(

Check warning on line 189 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L189

Added line #L189 was not covered by tests
const std::chrono::milliseconds& timeout)
{
return [sigset = make_and_block_signals({SIGQUIT, SIGTERM, SIGHUP, SIGUSR2}),

Check warning on line 192 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L192

Added line #L192 was not covered by tests
time = make_timespec(timeout)](const std::function<bool()>& condition) -> std::optional<int> {
// create a timer to send SIGUSR2 which unblocks this thread
sigevent sevp{};
sevp.sigev_notify = SIGEV_SIGNAL;
sevp.sigev_signo = SIGUSR2;

timer_t timer{};
if (timer_create(CLOCK_MONOTONIC, &sevp, &timer) == -1)
throw std::runtime_error(fmt::format("Could not create timer: {}", strerror(errno)));
timeout](const std::function<bool()>& condition) -> std::optional<int> {
std::mutex sig_mtx;
std::condition_variable sig_cv;
int sig = SIGUSR2;

Check warning on line 196 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L194-L196

Added lines #L194 - L196 were not covered by tests

// scope guard to make sure the timer is deleted once it's no longer needed
const auto timer_guard = sg::make_scope_guard([timer]() noexcept { timer_delete(timer); });
// A signal generator that triggers after `timeout`
AutoJoinThread signaler([&sig_mtx, &sig_cv, &sig, &timeout, signalee = pthread_self()] {
std::unique_lock lock(sig_mtx);
while (sig == SIGUSR2)

Check warning on line 201 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L199-L201

Added lines #L199 - L201 were not covered by tests
{
auto status = sig_cv.wait_for(lock, timeout);

Check warning on line 203 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L203

Added line #L203 was not covered by tests

// set timer interval and initial time to provided timeout
const itimerspec timer_interval{time, time};
if (timer_settime(timer, 0, &timer_interval, nullptr) == -1)
throw std::runtime_error(fmt::format("Could not set timer: {}", strerror(errno)));
if (sig == SIGUSR2 && status == std::cv_status::timeout)

Check warning on line 205 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L205

Added line #L205 was not covered by tests
{
pthread_kill(signalee, SIGUSR2);

Check warning on line 207 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L207

Added line #L207 was not covered by tests
}
}
});

Check warning on line 210 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L210

Added line #L210 was not covered by tests

// wait on signals and condition
int sig = SIGUSR2;
while (sig == SIGUSR2 && condition())
int ret = SIGUSR2;
while (ret == SIGUSR2 && condition())

Check warning on line 214 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L213-L214

Added lines #L213 - L214 were not covered by tests
{
// can't use sigtimedwait since macOS doesn't support it
sigwait(&sigset, &sig);
sigwait(&sigset, &ret);

Check warning on line 217 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L217

Added line #L217 was not covered by tests
}

{
std::unique_lock lock(sig_mtx);
sig = ret == SIGUSR2 ? 0 : ret;

Check warning on line 222 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L221-L222

Added lines #L221 - L222 were not covered by tests
}
sig_cv.notify_all();

Check warning on line 224 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L224

Added line #L224 was not covered by tests

// if sig is SIGUSR2 then we know we're exiting because condition() was false
return sig == SIGUSR2 ? std::nullopt : std::make_optional(sig);
return ret == SIGUSR2 ? std::nullopt : std::make_optional(sig);

Check warning on line 227 in src/platform/platform_unix.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/platform_unix.cpp#L227

Added line #L227 was not covered by tests
};
}
2 changes: 1 addition & 1 deletion src/sshfs_mount/sshfs_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ int main(int argc, char* argv[])
if (sig.has_value())
cout << "Received signal " << *sig << ". Stopping" << endl;
else
cout << "SFTP server thread stopped unexpectedly." << endl;
cerr << "SFTP server thread stopped unexpectedly." << endl;

sshfs_mount.stop();
exit(sig.has_value() ? EXIT_SUCCESS : EXIT_FAILURE);
Expand Down

0 comments on commit 979ee07

Please sign in to comment.