Skip to content

Commit ba48dbd

Browse files
committed
fix: Listen for ui_database_closed to ensure safe cleanup
src/plugin.cpp (modified): - StructorPlugin now inherits from event_listener_t to intercept UI notifications. - Added on_event implementation to trigger cleanup specifically on the ui_database_closed event. - Extracted shutdown logic (unregistering IDC functions, saving config) from the destructor into a new idempotent cleanup() method. - Added hook_event_listener/unhook_event_listener calls for HT_UI in the constructor and destructor. - Introduced a cleaned_up_ flag to prevent double-execution of the cleanup logic. Impact: - Ensures plugin resources and configuration are saved immediately when the database closes, rather than waiting for the plugin destructor. - Prevents potential crashes caused by accessing Qt widgets or internal state after the UI context has been destroyed.
1 parent a30cb60 commit ba48dbd

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

src/plugin.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,18 @@ static void unregister_idc_funcs() {
110110
}
111111

112112
/// Plugin descriptor
113-
class StructorPlugin : public plugmod_t {
113+
class StructorPlugin : public plugmod_t, public event_listener_t {
114114
public:
115115
StructorPlugin();
116116
~StructorPlugin() override;
117117

118118
bool idaapi run(size_t arg) override;
119+
ssize_t idaapi on_event(ssize_t code, va_list va) override;
119120

120121
private:
122+
void cleanup();
121123
bool initialized_ = false;
124+
bool cleaned_up_ = false;
122125
};
123126

124127
StructorPlugin::StructorPlugin() {
@@ -128,6 +131,9 @@ StructorPlugin::StructorPlugin() {
128131
// Register IDC functions
129132
register_idc_funcs();
130133

134+
// Hook UI notifications to cleanup before widget destruction
135+
hook_event_listener(HT_UI, this);
136+
131137
// Initialize UI
132138
if (UIIntegration::instance().initialize()) {
133139
initialized_ = true;
@@ -139,6 +145,14 @@ StructorPlugin::StructorPlugin() {
139145
}
140146

141147
StructorPlugin::~StructorPlugin() {
148+
unhook_event_listener(HT_UI, this);
149+
cleanup();
150+
}
151+
152+
void StructorPlugin::cleanup() {
153+
if (cleaned_up_) return;
154+
cleaned_up_ = true;
155+
142156
// Unregister IDC functions
143157
unregister_idc_funcs();
144158

@@ -149,7 +163,20 @@ StructorPlugin::~StructorPlugin() {
149163
if (Config::instance().is_dirty()) {
150164
Config::instance().save();
151165
}
166+
initialized_ = false;
167+
}
168+
}
169+
170+
ssize_t StructorPlugin::on_event(ssize_t code, va_list /*va*/) {
171+
switch (code) {
172+
case ui_database_closed:
173+
// Database closed - cleanup before Qt widgets are destroyed
174+
cleanup();
175+
break;
176+
default:
177+
break;
152178
}
179+
return 0;
153180
}
154181

155182
bool StructorPlugin::run(size_t arg) {

0 commit comments

Comments
 (0)