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
80 changes: 50 additions & 30 deletions src/slic3r/GUI/HttpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,19 @@ boost::asio::ip::port_type HttpServer::find_available_port(boost::asio::ip::port
}

void HttpServer::start()
{
{
std::lock_guard<std::mutex> lock(m_server_mtx);
start_locked();
}

// Started with m_server_mtx released: start_health_check() may join a
// retired health-check thread that is blocked in is_healthy() waiting for
// that lock — joining it under the lock would deadlock.
start_health_check();
}

void HttpServer::start_locked()
{
BOOST_LOG_TRIVIAL(info) << "start_http_service...";

Expand Down Expand Up @@ -332,13 +345,10 @@ void HttpServer::start()
}

BOOST_LOG_TRIVIAL(info) << "HTTP server started successfully on port " << port;

// 启动健康检查
BOOST_LOG_TRIVIAL(debug) << "Starting health check for HTTP server...";
start_health_check();

// 重启检查已集成到健康检查中,无需单独线程


// The health check is started by start()/restart() AFTER m_server_mtx
// is released (see start_health_check's join path).

} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Failed to start HTTP server: " << e.what();
std::string error_msg = "bury_point_Failed to start HTTP server on port " + std::to_string(port) + ": " + e.what();
Expand Down Expand Up @@ -379,33 +389,43 @@ void HttpServer::stop()
void HttpServer::restart()
{
BOOST_LOG_TRIVIAL(info) << "Restarting HTTP server on port " << port << "...";

BOOST_LOG_TRIVIAL(debug) << "Stopping current HTTP server...";
// 只停止HTTP服务器,不停止健康检查和重启检查线程
start_http_server = false;

// Hold the lock across teardown AND start(): if is_healthy() ran in the
// gap between the two it would see server_ == nullptr and trigger another
// restart on top of this one. Health-check / restart-check threads stay
// running (Edge); only the io server lifecycle is serialized here.
std::lock_guard<std::mutex> lock(m_server_mtx);
if (server_) {
boost::system::error_code ignored_ec;
server_->acceptor.close(ignored_ec);
server_->io_service.stop();

{
// Hold the lock across teardown AND start_locked(): if is_healthy()
// ran in the gap between the two it would see server_ == nullptr and
// trigger another restart on top of this one. Health-check /
// restart-check threads stay running (Edge); only the io server
// lifecycle is serialized here.
std::lock_guard<std::mutex> lock(m_server_mtx);
if (server_) {
boost::system::error_code ignored_ec;
server_->acceptor.close(ignored_ec);
server_->io_service.stop();
}
if (m_http_server_thread.joinable())
m_http_server_thread.join();
if (server_)
server_->stop_all();
server_.reset();

BOOST_LOG_TRIVIAL(debug) << "Waiting for resources to be released...";
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 等待资源释放

BOOST_LOG_TRIVIAL(debug) << "Starting new HTTP server...";
start_locked();
}
if (m_http_server_thread.joinable())
m_http_server_thread.join();
if (server_)
server_->stop_all();
server_.reset();

BOOST_LOG_TRIVIAL(debug) << "Waiting for resources to be released...";
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 等待资源释放

BOOST_LOG_TRIVIAL(debug) << "Starting new HTTP server...";
start();


// Must run with m_server_mtx released: a retired health-check thread can
// still be blocked in is_healthy() waiting for this lock, and
// start_health_check() joins it — joining under the lock deadlocks
// (T1 holds m_server_mtx waiting on join, T2 waits on m_server_mtx to
// finish is_healthy()).
start_health_check();

BOOST_LOG_TRIVIAL(info) << "HTTP server restart completed";
}

Expand Down
14 changes: 12 additions & 2 deletions src/slic3r/GUI/HttpServer.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef slic3r_Http_App_hpp_
#define slic3r_Http_App_hpp_

#include <atomic>
#include <iostream>
#include <mutex>
#include <stack>
Expand Down Expand Up @@ -142,8 +143,11 @@ class HttpServer
HttpServer(boost::asio::ip::port_type port = LOCALHOST_PORT);
~HttpServer(); // 添加析构函数

boost::thread m_http_server_thread;
bool start_http_server = false;
boost::thread m_http_server_thread;
// Written by the io thread's exception handler without holding m_server_mtx
// and read unlocked by is_started()/setPort() and the health-check loop,
// so it must be atomic.
std::atomic<bool> start_http_server = false;

// 添加自动健康检查相关成员
boost::thread m_health_check_thread;
Expand Down Expand Up @@ -211,6 +215,12 @@ class HttpServer
// sessions set is joined before teardown (see HttpServer::stop).
std::mutex m_server_mtx;

// Body of start() that runs under m_server_mtx. Deliberately does NOT
// start the health check: start_health_check() may join a retired
// health-check thread that is itself blocked in is_healthy() waiting for
// m_server_mtx, so it must only be called after the lock is released.
void start_locked();

std::unique_ptr<IOServer> server_{nullptr};

std::function<std::shared_ptr<Response>(const std::string&)> m_request_handler{&HttpServer::bbl_auth_handle_request};
Expand Down
12 changes: 11 additions & 1 deletion src/slic3r/GUI/SSWCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6292,7 +6292,17 @@ void SSWCP_MqttAgent_Instance::sw_mqtt_connect()
}
auto self = std::dynamic_pointer_cast<SSWCP_MqttAgent_Instance>(weak_ptr.lock());

engine->SetConnectionFailureCallback([engine]() {
// Capture the engine WEAKLY: this callback is stored inside the
// engine itself (MqttClient::connection_failure_callback_), so a
// shared_ptr capture would keep its refcount >= 1 forever and
// ~MqttClient — the only place the callback gets cleared — would
// never run, leaking the client and its Paho handles.
std::weak_ptr<MqttClient> weak_engine = engine;
engine->SetConnectionFailureCallback([weak_engine]() {
auto engine = weak_engine.lock();
if (!engine) {
return;
}
std::string msg = "";
engine->Disconnect(msg);
});
Expand Down