mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 05:27:50 +00:00
fix: moonraker printer agent hang on printer power cut
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include "IPrinterAgent.hpp"
|
#include "IPrinterAgent.hpp"
|
||||||
#include "libslic3r/Preset.hpp"
|
#include "libslic3r/Preset.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
|
#include "slic3r/GUI/DeviceCore/DevFilaSystem.h"
|
||||||
#include "slic3r/GUI/DeviceCore/DevManager.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()
|
void MoonrakerPrinterAgent::stop_status_stream()
|
||||||
{
|
{
|
||||||
ws_stop.store(true);
|
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()) {
|
if (ws_thread.joinable()) {
|
||||||
ws_thread.join();
|
ws_thread.join();
|
||||||
}
|
}
|
||||||
@@ -2113,6 +2122,25 @@ void MoonrakerPrinterAgent::run_status_stream(std::string dev_id, std::string ba
|
|||||||
stream.connect(results);
|
stream.connect(results);
|
||||||
|
|
||||||
websocket::stream<beast::tcp_stream> ws{std::move(stream)};
|
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) {
|
ws.set_option(websocket::stream_base::decorator([&](websocket::request_type& req) {
|
||||||
req.set(http::field::user_agent, "OrcaSlicer");
|
req.set(http::field::user_agent, "OrcaSlicer");
|
||||||
if (!api_key.empty()) {
|
if (!api_key.empty()) {
|
||||||
|
|||||||
@@ -240,6 +240,13 @@ private:
|
|||||||
std::atomic<uint64_t> ws_last_emit_ms{0};
|
std::atomic<uint64_t> ws_last_emit_ms{0};
|
||||||
std::thread ws_thread;
|
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
|
// 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).
|
// 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;
|
static constexpr uint64_t AMS_REFRESH_INTERVAL_MS = 10000;
|
||||||
|
|||||||
Reference in New Issue
Block a user