2.2.0 pre4 (#84)

* Fix crash

* Update: Flutter 1223

* fix: networktestdialog crash

* Update Flutter 1223

* bump profile version to 02.02.42.02

* bump min_firm_ver to 1.0.0
This commit is contained in:
xiaoyeliu
2025-12-23 15:52:08 +08:00
committed by GitHub
parent 792f1e12f3
commit 4423dce212
20 changed files with 74934 additions and 75209 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "Snapmaker", "name": "Snapmaker",
"version": "02.02.41.02", "version": "02.02.42.02",
"force_update": "0", "force_update": "0",
"description": "Snapmaker configurations", "description": "Snapmaker configurations",
"machine_model_list": [ "machine_model_list": [

View File

@@ -48,7 +48,7 @@
"20", "20",
"12" "12"
], ],
"machine_start_gcode": "\n;===== date: 20251222 =====================\n\nPRINT_START\nTIMELAPSE_START\nM140 S{bed_temperature_initial_layer_single}\nM104 T{initial_extruder} S140\nM204 S10000\n\n\nG28 X Y\n;===== 床面异物检测 ========\nT{initial_extruder}\nG90\nDEFECT_DETECTION_DETECT_BED\n;===== 取放头检测 =================\nSM_PRINT_CHECK_SWITCH_EXTRUDER\n\n;===== 粗回零 =================\nT{initial_extruder}\nM109 T{initial_extruder} S140\nG28 Z\n\n;===== 自动进料 & 挤出流量 & 预挤出 ======================\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=1 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=0\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=0\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=2 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=1\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=1\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=3 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=2\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=2\nSM_PRINT_AUTO_FEED EXTRUDER=3\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=3\n\n;===== 检测钢板 =================\nT{initial_extruder}\nM106 P2 S255\nMOVE_TO_DISCARD_FILAMENT_POSITION\nM109 S{nozzle_temperature[initial_extruder] - 50}\nROUGHLY_CLEAN_NOZZLE\nM104 S{nozzle_temperature[initial_extruder] - 90}\nG4 P2000\nROUGHLY_CLEAN_NOZZLE\nM107 P2\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nDETECT_BED_PLATE\n\n;===== 深度清洁喷嘴 =================\nG90\nG0 Z5 F10000\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nM109 S{nozzle_temperature[initial_extruder] - 50}\nROUGHLY_CLEAN_NOZZLE\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nFINELY_CLEAN_NOZZLE_STAGE_1\nG0 Z5 F10000\nROUGHLY_CLEAN_NOZZLE\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nFINELY_CLEAN_NOZZLE_STAGE_2\n\n;===== 精回零 =================\nM106 P2 S255\nM109 S{nozzle_temperature[initial_extruder] - 90}\nM190 S{bed_temperature_initial_layer_single}\nM107 P2\nG90\nG0 Z5 F10000\nG28 Z\n\n;===== 热床调平 =================\nBED_MESH_CALIBRATE PROBE_COUNT=11,11\n\nG90\nG1 Z1.5\nG0 X10 Y3 Z2 F18000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nM83\nG1 X110 E15 F360\nG1 Z1.5\n\nG90\nM106 S0\n", "machine_start_gcode": ";===== date: 20251222 =====================\n\nPRINT_START\nDEFECT_DETECTION_START\nSET_PRINT_STATS_INFO TOTAL_LAYER={total_layer_count}\nSET_PRINT_STATS_INFO CURRENT_LAYER=0\nTIMELAPSE_START\nM140 S{bed_temperature_initial_layer_single}\nM104 T{initial_extruder} S140\nM204 S10000\n\nG28 X Y\n;===== 床面异物检测 ========\nT{initial_extruder}\nG90\nDEFECT_DETECTION_DETECT_BED\n;===== 取放头检测 =================\nSM_PRINT_CHECK_SWITCH_EXTRUDER\n\n;===== 自动进料 & 挤出流量 & 预挤出 ======================\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=1 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=0\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=0\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=2 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=1\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=1\nSM_PRINT_EXTRUDER_PREHEAT EXTRUDER=3 TEMP=140\nSM_PRINT_AUTO_FEED EXTRUDER=2\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=2\nSM_PRINT_AUTO_FEED EXTRUDER=3\nSM_PRINT_FLOW_CALIBRATE EXTRUDER=3\nM104 S0 T0 A0\nM104 S0 T1 A0\nM104 S0 T2 A0\nM104 S0 T3 A0\nM104 T{initial_extruder} S{nozzle_temperature[initial_extruder] - 90}\n\n;===== 粗回零 =================\nT{initial_extruder}\nM106 S255\nM106 P2 S0\nMOVE_TO_DISCARD_FILAMENT_POSITION\nM109 T{initial_extruder} S{nozzle_temperature[initial_extruder] - 90}\nROUGHLY_CLEAN_NOZZLE_WITH_DISCARD\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nG28 Z I140 J140\n\n;===== 检测钢板 =================\nDETECT_BED_PLATE\n\n;===== 深度清洁喷嘴 =================\nG90\nG0 Z5 F10000\nMOVE_TO_DISCARD_FILAMENT_POSITION\nM109 S{nozzle_temperature[initial_extruder] - 50}\nROUGHLY_CLEAN_NOZZLE\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nFINELY_CLEAN_NOZZLE_STAGE_1\nM104 S{nozzle_temperature[initial_extruder] - 90}\nG0 Z5 F10000\nMOVE_TO_DISCARD_FILAMENT_POSITION\nROUGHLY_CLEAN_NOZZLE\nMOVE_TO_XY_IDLE_POSITION_EXTRUDER\nFINELY_CLEAN_NOZZLE_STAGE_2\n\n;===== 精回零 =================\nM106 S255\nM109 S{nozzle_temperature[initial_extruder] - 90}\nM190 S{bed_temperature_initial_layer_single}\nM107 P2\nG90\nG0 Z5 F10000\nG28 Z\n\n;===== 热床调平 =================\nBED_MESH_CALIBRATE PROBE_COUNT=11,11\n\n;===== 画起始线 =================\nG90\nG1 Z1.5\nG0 X10 Y3 Z2 F18000\nM109 S{nozzle_temperature_initial_layer[initial_extruder]}\nG1 Z0.2\nM83\nG1 X110 E15 F360\nG1 Z1.5\n\nG90\nM106 S0",
"machine_tool_change_time": "5", "machine_tool_change_time": "5",
"max_layer_height": [ "max_layer_height": [
"0.32", "0.32",
@@ -176,10 +176,10 @@
"0.4" "0.4"
], ],
"z_hop_types": [ "z_hop_types": [
"Normal Lift", "Auto Lift",
"Normal Lift", "Auto Lift",
"Normal Lift", "Auto Lift",
"Normal Lift" "Auto Lift"
], ],
"enable_filament_ramming": "0", "enable_filament_ramming": "0",
"extruder_clearance_height_to_rod": "27.5", "extruder_clearance_height_to_rod": "27.5",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -313,6 +313,9 @@
"time_lapse_video_start_downloading": "Start downloading...", "time_lapse_video_start_downloading": "Start downloading...",
"time_lapse_video_export_video_failed": "Export video failed", "time_lapse_video_export_video_failed": "Export video failed",
"Network may be unstable, device connection may be unreliable.": "Network may be unstable, device connection may be unreliable",
"network_unstable_partial_operation_failed": "Network unstable, partial operation may failed",
"Check": "Check", "Check": "Check",
"default_exception_title": "Exception", "default_exception_title": "Exception",

View File

@@ -376,6 +376,9 @@
"loading...": "加载中...", "loading...": "加载中...",
"Loading...": "加载中...", "Loading...": "加载中...",
"Login...": "登录中...", "Login...": "登录中...",
"Network may be unstable, device connection may be unreliable": "网络不稳定,设备连接可能不可靠",
"network_unstable_partial_operation_failed": "网络不稳定,部分操作可能失败",
"Heated Bed Temp.": "热床温度", "Heated Bed Temp.": "热床温度",
"Print Speed": "打印速度", "Print Speed": "打印速度",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -11,6 +11,6 @@ _flutter.buildConfig = {"engineRevision":"b8800d88be4866db1b15f8b954ab2573bba996
_flutter.loader.load({ _flutter.loader.load({
serviceWorkerSettings: { serviceWorkerSettings: {
serviceWorkerVersion: "551267088" serviceWorkerVersion: "122636570"
} }
}); });

View File

@@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache'; const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache'; const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {"flutter_bootstrap.js": "15aa1a61e2fffe7f5fe19354f3375131", const RESOURCES = {"flutter_bootstrap.js": "360fcb7ece74a6ddc0b90b99cfaf61e8",
"version.json": "1d3d3b6efcc44899280498cbf3bb2e8a", "version.json": "970f76bce879e0e8a3c71f92c31d53be",
"index.html": "0ea1997f6c2c3b34b0f1fb58390e10c7", "index.html": "0ea1997f6c2c3b34b0f1fb58390e10c7",
"/": "0ea1997f6c2c3b34b0f1fb58390e10c7", "/": "0ea1997f6c2c3b34b0f1fb58390e10c7",
"main.dart.js": "345b9e96e297d5fd652acfa9f7e5fe6e", "main.dart.js": "a295ed043d6a84d80de1eb3143542830",
"flutter.js": "f31737fb005cd3a3c6bd9355efd33061", "flutter.js": "f31737fb005cd3a3c6bd9355efd33061",
"version.changelog": "1ba1bc2d44d055158f7719b3b2ffe3a7", "version.changelog": "1ba1bc2d44d055158f7719b3b2ffe3a7",
"favicon.png": "be8d1ab28c20907c9869c345d0482962", "favicon.png": "be8d1ab28c20907c9869c345d0482962",
@@ -16,20 +16,20 @@ const RESOURCES = {"flutter_bootstrap.js": "15aa1a61e2fffe7f5fe19354f3375131",
"icons/Icon-maskable-512.png": "4870fb6720f4fcad016cb582589d136d", "icons/Icon-maskable-512.png": "4870fb6720f4fcad016cb582589d136d",
"icons/Icon-512.png": "343022ac1c56796cb7ff635faf0646ef", "icons/Icon-512.png": "343022ac1c56796cb7ff635faf0646ef",
"manifest.json": "901d86fb8842ec0d66225a542131d689", "manifest.json": "901d86fb8842ec0d66225a542131d689",
"assets/AssetManifest.json": "7ce73ec4dfdc30e547047d3ef562c880", "assets/AssetManifest.json": "72e2d76c872feeb5bb96bcc8facd729c",
"assets/NOTICES": "d453b0291cf6ccfc5ced86766a1aa652", "assets/NOTICES": "d453b0291cf6ccfc5ced86766a1aa652",
"assets/FontManifest.json": "0dc3d44d47c5e2636cdca4babafb2396", "assets/FontManifest.json": "0dc3d44d47c5e2636cdca4babafb2396",
"assets/AssetManifest.bin.json": "2e5c373110fd3fc0e6f113a5a850ed9d", "assets/AssetManifest.bin.json": "e834d2b760d8a73a48c833be3c19ba6e",
"assets/packages/lava_device_control/assets/files/filament.json": "54d21ade78e6cd6025306530023b094d", "assets/packages/lava_device_control/assets/files/filament.json": "54d21ade78e6cd6025306530023b094d",
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "391ff5f9f24097f4f6e4406690a06243", "assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "391ff5f9f24097f4f6e4406690a06243",
"assets/packages/fluttertoast/assets/toastify.js": "56e2c9cedd97f10e7e5f1cebd85d53e3", "assets/packages/fluttertoast/assets/toastify.js": "56e2c9cedd97f10e7e5f1cebd85d53e3",
"assets/packages/fluttertoast/assets/toastify.css": "a85675050054f179444bc5ad70ffc635", "assets/packages/fluttertoast/assets/toastify.css": "a85675050054f179444bc5ad70ffc635",
"assets/packages/wakelock_plus/assets/no_sleep.js": "7748a45cd593f33280669b29c2c8919a", "assets/packages/wakelock_plus/assets/no_sleep.js": "7748a45cd593f33280669b29c2c8919a",
"assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce", "assets/shaders/ink_sparkle.frag": "ecc85a2e95f5e9f53123dcaf8cb9b6ce",
"assets/AssetManifest.bin": "ca2256603a4abe62eddd37a2eac154c5", "assets/AssetManifest.bin": "e6421692063a637e740d83842b7b806d",
"assets/fonts/MaterialIcons-Regular.otf": "aa361df3c4cfa80e7a16cc8899e3c663", "assets/fonts/MaterialIcons-Regular.otf": "aa361df3c4cfa80e7a16cc8899e3c663",
"assets/assets/i10n/zh-CN.json": "4c3107a1754a5dfa5539f945d27cb1b0", "assets/assets/i10n/zh-CN.json": "11eb31598543608b7fb935f5673cbaef",
"assets/assets/i10n/en.json": "cd7528d64290e2ed607eab79ad18ab34", "assets/assets/i10n/en.json": "552a55a8589175d6bd2422e3d4acc5ca",
"assets/assets/images/deviceNoResponse.webp": "1ca23a7feedfdc34362ea5789ccf895b", "assets/assets/images/deviceNoResponse.webp": "1ca23a7feedfdc34362ea5789ccf895b",
"assets/assets/images/deviceAuthorized.webp": "8eb814193bed15cec22658018871aba8", "assets/assets/images/deviceAuthorized.webp": "8eb814193bed15cec22658018871aba8",
"assets/assets/images/IpInputGuide.webp": "06c11ce1dadc2910676aec6d40a5eea5", "assets/assets/images/IpInputGuide.webp": "06c11ce1dadc2910676aec6d40a5eea5",
@@ -42,7 +42,6 @@ const RESOURCES = {"flutter_bootstrap.js": "15aa1a61e2fffe7f5fe19354f3375131",
"assets/assets/images/printtaskDefault.png": "2d53add29c1647300def2ec024574307", "assets/assets/images/printtaskDefault.png": "2d53add29c1647300def2ec024574307",
"assets/assets/images/deviceRejected.webp": "cb02f340100006ad22965c215fc6726c", "assets/assets/images/deviceRejected.webp": "cb02f340100006ad22965c215fc6726c",
"assets/assets/images/ipInputGuideCN.webp": "6ff23fea6ac4212d222500ba1cbbddcf", "assets/assets/images/ipInputGuideCN.webp": "6ff23fea6ac4212d222500ba1cbbddcf",
"assets/assets/images/bindPrinter.png": "b35f610897d7c4e891f3b0dc56d193f7",
"assets/assets/images/3dprinter.png": "4515f02e633d58a1119c2f55114da32b", "assets/assets/images/3dprinter.png": "4515f02e633d58a1119c2f55114da32b",
"assets/assets/images/logo.png": "b1a7a2105873616de883cf2662a2bf9c", "assets/assets/images/logo.png": "b1a7a2105873616de883cf2662a2bf9c",
"assets/assets/images/controlDefault.png": "1122ed99c68469d307335e55350c2bff", "assets/assets/images/controlDefault.png": "1122ed99c68469d307335e55350c2bff",

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"app_name":"orca","version":"2.1.2","build_number":"20251222224146","package_name":"orca"} {"app_name":"orca","version":"2.1.2","build_number":"20251223154027","package_name":"orca"}

View File

@@ -7,7 +7,7 @@
#define SLIC3R_APP_KEY "Snapmaker_Orca" #define SLIC3R_APP_KEY "Snapmaker_Orca"
#define SLIC3R_VERSION "01.10.01.50" #define SLIC3R_VERSION "01.10.01.50"
#define Snapmaker_VERSION "2.2.0" #define Snapmaker_VERSION "2.2.0"
#define MIN_FIRM_VER "0.8.4" #define MIN_FIRM_VER "1.0.0"
#ifndef GIT_COMMIT_HASH #ifndef GIT_COMMIT_HASH
#define GIT_COMMIT_HASH "0000000" // 0000000 means uninitialized #define GIT_COMMIT_HASH "0000000" // 0000000 means uninitialized
#endif #endif

View File

@@ -1122,7 +1122,7 @@ GUI_App::GUI_App()
m_fltviews.set_app(this); m_fltviews.set_app(this);
} }
void GUI_App::shutdown() void GUI_App::shutdown(bool isRecreate)
{ {
BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown enter"; BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown enter";
@@ -1156,7 +1156,7 @@ void GUI_App::shutdown()
} }
// Delete WebPresetDialog to ensure proper cleanup // Delete WebPresetDialog to ensure proper cleanup
if (SSWCP_MqttAgent_Instance::m_dialog != nullptr) { if (SSWCP_MqttAgent_Instance::m_dialog != nullptr && !isRecreate) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": destroy WebPresetDialog"); BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": destroy WebPresetDialog");
delete SSWCP_MqttAgent_Instance::m_dialog; delete SSWCP_MqttAgent_Instance::m_dialog;
SSWCP_MqttAgent_Instance::m_dialog = nullptr; SSWCP_MqttAgent_Instance::m_dialog = nullptr;
@@ -3614,7 +3614,8 @@ void GUI_App::recreate_GUI(const wxString &msg_name)
update_http_extra_header(); update_http_extra_header();
mainframe->shutdown(); mainframe->shutdown(true);
ProgressDialog dlg(msg_name, msg_name, 100, nullptr, wxPD_AUTO_HIDE); ProgressDialog dlg(msg_name, msg_name, 100, nullptr, wxPD_AUTO_HIDE);
dlg.Pulse(); dlg.Pulse();
dlg.Update(10, _L("Rebuild") + dots); dlg.Update(10, _L("Rebuild") + dots);

View File

@@ -416,7 +416,7 @@ private:
// Process command line parameters cached in this->init_params, // Process command line parameters cached in this->init_params,
// load configs, STLs etc. // load configs, STLs etc.
void post_init(); void post_init();
void shutdown(); void shutdown(bool isRecreate = false);
// If formatted for github, plaintext with OpenGL extensions enclosed into <details>. // If formatted for github, plaintext with OpenGL extensions enclosed into <details>.
// Otherwise HTML formatted for the system info dialog. // Otherwise HTML formatted for the system info dialog.
static std::string get_gl_info(bool for_github); static std::string get_gl_info(bool for_github);

View File

@@ -889,7 +889,7 @@ void MainFrame::update_layout()
} }
// Called when closing the application and when switching the application language. // Called when closing the application and when switching the application language.
void MainFrame::shutdown() void MainFrame::shutdown(bool isRecreate)
{ {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown enter"; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown enter";
// BBS: backup // BBS: backup
@@ -956,7 +956,7 @@ void MainFrame::shutdown()
// to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing // to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing
wxGetApp().tabs_list.clear(); wxGetApp().tabs_list.clear();
wxGetApp().model_tabs_list.clear(); wxGetApp().model_tabs_list.clear();
wxGetApp().shutdown(); wxGetApp().shutdown(isRecreate);
// BBS: why clear ? // BBS: why clear ?
//wxGetApp().plater_ = nullptr; //wxGetApp().plater_ = nullptr;
@@ -2308,9 +2308,25 @@ static wxMenu* generate_help_menu()
}); });
append_menu_item(helpMenu, wxID_ANY, _L("Open Network Test"), _L("Open Network Test"), [](wxCommandEvent&) { append_menu_item(helpMenu, wxID_ANY, _L("Open Network Test"), _L("Open Network Test"), [](wxCommandEvent&) {
NetworkTestDialog dlg(wxGetApp().mainframe); // Use shared_ptr to manage dialog lifetime
dlg.ShowModal(); auto dlg = std::make_shared<NetworkTestDialog>(wxGetApp().mainframe);
}); dlg->ShowModal();
// Keep dialog alive for 2 seconds after closing to allow background threads to finish
// Use a timer to delay the destruction
class DelayedReleaseTimer : public wxTimer {
std::shared_ptr<NetworkTestDialog> m_dialog;
public:
DelayedReleaseTimer(std::shared_ptr<NetworkTestDialog> dlg) : m_dialog(std::move(dlg)) {
StartOnce(5000); // 5 seconds delay
}
void Notify() override {
m_dialog.reset(); // Release the dialog
delete this; // Delete the timer itself
}
};
new DelayedReleaseTimer(dlg); // Timer will delete itself
});
// About // About
#ifndef __APPLE__ #ifndef __APPLE__

View File

@@ -246,7 +246,7 @@ public:
void update_layout(); void update_layout();
// Called when closing the application and when switching the application language. // Called when closing the application and when switching the application language.
void shutdown(); void shutdown(bool isRecreate = false);
Plater* plater() { return m_plater; } Plater* plater() { return m_plater; }

View File

@@ -293,6 +293,11 @@ NetworkTestDialog::~NetworkTestDialog()
m_closing.store(true); m_closing.store(true);
m_download_cancel = true; m_download_cancel = true;
cleanup_threads(); cleanup_threads();
// Small delay to allow any in-flight update_status calls to complete
// before destroying the shared_ptr control block
boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
// Break the self-reference to avoid issues // Break the self-reference to avoid issues
self_ptr.reset(); self_ptr.reset();
} }
@@ -1059,11 +1064,27 @@ void NetworkTestDialog::on_dpi_changed(const wxRect &suggested_rect)
void NetworkTestDialog::update_status(int job_id, wxString info) void NetworkTestDialog::update_status(int job_id, wxString info)
{ {
// Early exit if dialog is closing - don't access any members
if (m_closing.load()) return; if (m_closing.load()) return;
auto evt = new wxCommandEvent(EVT_UPDATE_RESULT, this->GetId());
evt->SetString(info); // Use try-catch to protect against accessing destroyed dialog
evt->SetInt(job_id); try {
wxQueueEvent(this, evt); // Double check before creating event
if (m_closing.load()) return;
auto evt = new wxCommandEvent(EVT_UPDATE_RESULT, this->GetId());
evt->SetString(info);
evt->SetInt(job_id);
// Triple check before queuing - race condition window is very small
if (!m_closing.load()) {
wxQueueEvent(this, evt);
} else {
delete evt;
}
} catch (...) {
// Silently ignore if dialog was destroyed during operation
}
} }
void NetworkTestDialog::cleanup_threads() void NetworkTestDialog::cleanup_threads()
@@ -1072,11 +1093,11 @@ void NetworkTestDialog::cleanup_threads()
for (int i = 0; i < TEST_JOB_MAX; i++) { for (int i = 0; i < TEST_JOB_MAX; i++) {
if (test_job[i] != nullptr) { if (test_job[i] != nullptr) {
if (test_job[i]->joinable()) { if (test_job[i]->joinable()) {
// Try to join with a short timeout (200ms) // Try to join with longer timeout (1000ms) to reduce chance of detach
// If thread is blocked in wxExecute, don't wait indefinitely // Threads should check m_closing and exit promptly
if (!test_job[i]->try_join_for(boost::chrono::milliseconds(200))) { if (!test_job[i]->try_join_for(boost::chrono::milliseconds(1000))) {
// Thread didn't finish in time, detach it to avoid blocking // Thread didn't finish in time, detach it to avoid blocking
// The thread will check m_closing and exit safely // The thread will check m_closing and should exit safely
test_job[i]->detach(); test_job[i]->detach();
BOOST_LOG_TRIVIAL(warning) << "Thread " << i << " didn't finish in time, detached"; BOOST_LOG_TRIVIAL(warning) << "Thread " << i << " didn't finish in time, detached";
} }
@@ -1089,8 +1110,8 @@ void NetworkTestDialog::cleanup_threads()
// Clean up sequence job thread // Clean up sequence job thread
if (m_sequence_job != nullptr) { if (m_sequence_job != nullptr) {
if (m_sequence_job->joinable()) { if (m_sequence_job->joinable()) {
// Try to join with a short timeout (200ms) // Try to join with longer timeout (1000ms)
if (!m_sequence_job->try_join_for(boost::chrono::milliseconds(200))) { if (!m_sequence_job->try_join_for(boost::chrono::milliseconds(1000))) {
// Thread didn't finish in time, detach it // Thread didn't finish in time, detach it
m_sequence_job->detach(); m_sequence_job->detach();
BOOST_LOG_TRIVIAL(warning) << "Sequence job thread didn't finish in time, detached"; BOOST_LOG_TRIVIAL(warning) << "Sequence job thread didn't finish in time, detached";

View File

@@ -516,8 +516,28 @@ void SSWCP_Instance::sw_OpenNetworkDialog() {
finish_job(); finish_job();
wxGetApp().CallAfter([]() { wxGetApp().CallAfter([]() {
NetworkTestDialog dlg(wxGetApp().mainframe); // Use shared_ptr to manage dialog lifetime
dlg.ShowModal(); auto dlg = std::make_shared<NetworkTestDialog>(wxGetApp().mainframe);
dlg->ShowModal();
// Keep dialog alive for 2 seconds after closing to allow background threads to finish
// Use a timer to delay the destruction
class DelayedReleaseTimer : public wxTimer
{
std::shared_ptr<NetworkTestDialog> m_dialog;
public:
DelayedReleaseTimer(std::shared_ptr<NetworkTestDialog> dlg) : m_dialog(std::move(dlg))
{
StartOnce(5000); // 5 seconds delay
}
void Notify() override
{
m_dialog.reset(); // Release the dialog
delete this; // Delete the timer itself
}
};
new DelayedReleaseTimer(dlg);
}); });
} }
catch (std::exception& e) { catch (std::exception& e) {

View File

@@ -11,7 +11,7 @@ if(NOT DEFINED BBL_INTERNAL_TESTING)
set(BBL_INTERNAL_TESTING "0") set(BBL_INTERNAL_TESTING "0")
endif() endif()
set(Snapmaker_VERSION "2.2.0") set(Snapmaker_VERSION "2.2.0")
set(MIN_FIRM_VER "0.8.4") set(MIN_FIRM_VER "1.0.0")
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)"
Snapmaker_VERSION_MATCH ${Snapmaker_VERSION}) Snapmaker_VERSION_MATCH ${Snapmaker_VERSION})
set(ORCA_VERSION_MAJOR ${CMAKE_MATCH_1}) set(ORCA_VERSION_MAJOR ${CMAKE_MATCH_1})