Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## Unreleased

- Linux hosts now terminate on SIGTERM/SIGINT. The host scaffold and the
Taskboard example install Rivet's shutdown hook so a termination signal
runs the same orderly backend shutdown as the GTK shutdown signal and
then exits; previously the embedded backend died on the signal while the
GTK process stayed up, leaving a window that could not search or run
anything (observed on Fulcrum 0.4.1: `kill` left a half-dead app that
only SIGKILL would remove).
- Honor `linux-binary-name` in `rivet.rktd`: the Linux build stage, package
staging, verification, and launch smoke now use the configured executable
name instead of the hardcoded scaffold name `RivetHost` (default
Expand Down
11 changes: 11 additions & 0 deletions examples/taskboard/linux/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <memory>
#include <mutex>
Expand Down Expand Up @@ -527,12 +528,22 @@ void on_shutdown(GApplication*, gpointer) {
if (g_state.backend) g_state.backend->stop();
}

// SIGTERM/SIGINT bypass the GTK main loop; run the same orderly shutdown
// the GTK shutdown signal would have run, then the hook hard-exits.
void perform_orderly_shutdown() { on_shutdown(nullptr, nullptr); }

} // namespace

int main(int argc, char** argv) {
auto* app = gtk_application_new("dev.rivet.taskboard", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect(app, "activate", G_CALLBACK(on_activate), nullptr);
g_signal_connect(app, "shutdown", G_CALLBACK(on_shutdown), nullptr);
try {
rivet::system::InstallShutdownHook(perform_orderly_shutdown);
} catch (std::exception const& error) {
std::fputs((std::string{"shutdown hook unavailable: "} + error.what() + "\n").c_str(),
stderr);
}
int const status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
Expand Down
16 changes: 16 additions & 0 deletions platform/linux/host/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@

#include <atomic>
#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <thread>

#include "GeneratedBackend.hpp"
#include "system_services.hpp"
#include "theme.hpp"

namespace {
Expand Down Expand Up @@ -264,13 +267,26 @@ void on_shutdown(GApplication*, gpointer) {
}
}

// SIGTERM/SIGINT bypass the GTK main loop, so the shutdown signal handler
// alone would leave the window alive over a dead backend. The watcher
// thread runs this same cleanup and then hard-exits; keep it synchronous
// and allocation-light.
void perform_orderly_shutdown() { on_shutdown(nullptr, nullptr); }

} // namespace

int main(int argc, char** argv) {
auto* app = gtk_application_new("dev.rivet.host",
G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect(app, "activate", G_CALLBACK(on_activate), nullptr);
g_signal_connect(app, "shutdown", G_CALLBACK(on_shutdown), nullptr);
try {
rivet::system::InstallShutdownHook(perform_orderly_shutdown);
} catch (std::exception const& error) {
std::fputs((std::string{"shutdown hook unavailable: "} + error.what() +
"\n").c_str(),
stderr);
}
int const status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
Expand Down
Loading