mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-15 21:17:41 +00:00
fix: moonraker printer agent hang on printer power cut
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "IPrinterAgent.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
|
||||
#include "slic3r/GUI/DeviceCore/DevManager.h"
|
||||
@@ -2077,6 +2078,14 @@ void MoonrakerPrinterAgent::start_status_stream(const std::string& dev_id, const
|
||||
void MoonrakerPrinterAgent::stop_status_stream()
|
||||
{
|
||||
ws_stop.store(true);
|
||||
{
|
||||
// Wake a blocked synchronous ws.read()/ws.write() in run_status_stream();
|
||||
// ws_stop by itself is only observed between reads.
|
||||
std::lock_guard<std::mutex> lock(ws_abort_mutex);
|
||||
if (ws_abort_io) {
|
||||
ws_abort_io();
|
||||
}
|
||||
}
|
||||
if (ws_thread.joinable()) {
|
||||
ws_thread.join();
|
||||
}
|
||||
@@ -2113,6 +2122,25 @@ void MoonrakerPrinterAgent::run_status_stream(std::string dev_id, std::string ba
|
||||
stream.connect(results);
|
||||
|
||||
websocket::stream<beast::tcp_stream> ws{std::move(stream)};
|
||||
|
||||
// Allow stop_status_stream() to force this socket shut so a blocked
|
||||
// synchronous ws.read()/ws.write() returns with an error (Beast's
|
||||
// expires_after() does not bound synchronous operations). Declared
|
||||
// after `ws` so the hook is cleared before `ws` is destroyed on every
|
||||
// exit path (fallthrough, break, exception); ws_abort_mutex keeps the
|
||||
// hook from running against a half-destroyed `ws`.
|
||||
ScopeGuard ws_abort_guard([this] {
|
||||
std::lock_guard<std::mutex> lock(ws_abort_mutex);
|
||||
ws_abort_io = nullptr;
|
||||
});
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(ws_abort_mutex);
|
||||
ws_abort_io = [&ws] {
|
||||
beast::error_code ec;
|
||||
ws.next_layer().socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||
};
|
||||
}
|
||||
|
||||
ws.set_option(websocket::stream_base::decorator([&](websocket::request_type& req) {
|
||||
req.set(http::field::user_agent, "OrcaSlicer");
|
||||
if (!api_key.empty()) {
|
||||
|
||||
@@ -240,6 +240,13 @@ private:
|
||||
std::atomic<uint64_t> ws_last_emit_ms{0};
|
||||
std::thread ws_thread;
|
||||
|
||||
// stop_status_stream() invokes ws_abort_io to wake a blocked synchronous
|
||||
// ws.read()/ws.write()/handshake in run_status_stream(): ws_stop is only
|
||||
// observed between reads, and Beast's expires_after() does not bound
|
||||
// synchronous operations.
|
||||
std::mutex ws_abort_mutex;
|
||||
std::function<void()> ws_abort_io; // guarded by ws_abort_mutex
|
||||
|
||||
// AMS/filament refresh cadence, independent of telemetry dispatch so a steady
|
||||
// stream of status updates can't starve it (ws_last_emit_ms is reset by those).
|
||||
static constexpr uint64_t AMS_REFRESH_INTERVAL_MS = 10000;
|
||||
|
||||
Reference in New Issue
Block a user