fix(interop): resolve native resource leaks in GTK and WebKit interop
All checks were successful
CI / Build (Linux) (push) Successful in 21s
All checks were successful
CI / Build (Linux) (push) Successful in 21s
Fix critical memory leaks identified in architecture review: Add signal handler disconnection in WebKitNative (load-changed and script-dialog signals now properly cleaned up), implement GTK idle callback cleanup with automatic removal on completion, add dlclose() calls for WebKit library handles, track GTK signal IDs in GtkSkiaSurfaceWidget for proper disposal. Replace empty catch blocks in GestureManager with logged exception handling. Add WebKitNative.Cleanup() and GtkNative.ClearCallbacks() methods for application shutdown.
This commit is contained in:
@@ -99,8 +99,9 @@ public class AppInfoService : IAppInfo
|
||||
UseShellExecute = true
|
||||
});
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
DiagnosticLog.Debug("AppInfoService", "Settings launch fallback failed", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +129,9 @@ public class ConnectivityService : IConnectivity, IDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
DiagnosticLog.Debug("ConnectivityService", "Gateway check failed", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -137,8 +137,9 @@ public class DeviceDisplayService : IDeviceDisplay
|
||||
});
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
DiagnosticLog.Debug("DeviceDisplayService", "Display info refresh failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,9 @@ public class DeviceInfoService : IDeviceInfo
|
||||
return result;
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
DiagnosticLog.Debug("DeviceInfoService", "OS version parsing failed", ex);
|
||||
}
|
||||
return new Version(1, 0);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,17 @@ public static class DiagnosticLog
|
||||
System.Console.WriteLine($"[{tag}] {message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a debug diagnostic message with exception details.
|
||||
/// Only compiled in DEBUG builds.
|
||||
/// </summary>
|
||||
[Conditional("DEBUG")]
|
||||
public static void Debug(string tag, string message, Exception ex)
|
||||
{
|
||||
if (IsEnabled)
|
||||
System.Console.WriteLine($"[{tag}] {message}: {ex.Message}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an informational diagnostic message (always writes when enabled, not conditional on DEBUG).
|
||||
/// Use for important operational messages that should appear in release builds when logging is enabled.
|
||||
|
||||
@@ -133,7 +133,7 @@ public class Fcitx5InputMethodService : IInputMethodService, IDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("Fcitx5InputMethodService", "Commit signal processing failed", ex); }
|
||||
}
|
||||
|
||||
private async Task ProcessPreeditSignal(StreamReader reader)
|
||||
@@ -160,7 +160,7 @@ public class Fcitx5InputMethodService : IInputMethodService, IDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("Fcitx5InputMethodService", "Preedit signal processing failed", ex); }
|
||||
}
|
||||
|
||||
public void SetFocus(IInputContext? context)
|
||||
@@ -284,7 +284,7 @@ public class Fcitx5InputMethodService : IInputMethodService, IDisposable
|
||||
_dBusMonitor?.Kill();
|
||||
_dBusMonitor?.Dispose();
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("Fcitx5InputMethodService", "D-Bus monitor cleanup failed", ex); }
|
||||
|
||||
if (!string.IsNullOrEmpty(_inputContextPath))
|
||||
{
|
||||
|
||||
@@ -51,6 +51,13 @@ public static class GtkThemeService
|
||||
return;
|
||||
}
|
||||
|
||||
// Unreference previous CSS provider to prevent leak
|
||||
if (_currentCssProvider != IntPtr.Zero)
|
||||
{
|
||||
GtkNative.g_object_unref(_currentCssProvider);
|
||||
_currentCssProvider = IntPtr.Zero;
|
||||
}
|
||||
|
||||
// Create new CSS provider
|
||||
IntPtr newProvider = GtkNative.gtk_css_provider_new();
|
||||
if (newProvider == IntPtr.Zero)
|
||||
@@ -63,6 +70,7 @@ public static class GtkThemeService
|
||||
if (!GtkNative.gtk_css_provider_load_from_data(newProvider, css, -1, IntPtr.Zero))
|
||||
{
|
||||
DiagnosticLog.Error("GtkThemeService", "Failed to load CSS data");
|
||||
GtkNative.g_object_unref(newProvider);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -464,7 +464,7 @@ public class HiDpiService
|
||||
return textScale;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("HiDpiService", "Font scale factor detection failed", ex); }
|
||||
|
||||
return _scaleFactor;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class NotificationService
|
||||
_dBusMonitor?.Dispose();
|
||||
_dBusMonitor = null;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("NotificationService", "D-Bus monitor cleanup failed", ex); }
|
||||
}
|
||||
|
||||
private async Task MonitorNotificationSignals()
|
||||
@@ -155,7 +155,7 @@ public class NotificationService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("NotificationService", "Action invoked processing failed", ex); }
|
||||
}
|
||||
|
||||
private async Task ProcessNotificationClosed(StreamReader reader)
|
||||
@@ -192,7 +192,7 @@ public class NotificationService
|
||||
context?.Tag));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("NotificationService", "Notification closed processing failed", ex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -270,7 +270,7 @@ public class NotificationService
|
||||
|
||||
_activeNotifications.TryRemove(notificationId, out _);
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("NotificationService", "Notification cancel failed", ex); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -160,7 +160,7 @@ public class SystemThemeService
|
||||
if (output.ToLowerInvariant().Contains("dark"))
|
||||
return SystemTheme.Dark;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "GNOME theme detection failed", ex); }
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -186,7 +186,7 @@ public class SystemThemeService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "KDE theme detection failed", ex); }
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ public class SystemThemeService
|
||||
if (output.ToLowerInvariant().Contains("dark"))
|
||||
return SystemTheme.Dark;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "XFCE theme detection failed", ex); }
|
||||
|
||||
return DetectGtkTheme();
|
||||
}
|
||||
@@ -212,7 +212,7 @@ public class SystemThemeService
|
||||
if (output.ToLowerInvariant().Contains("dark"))
|
||||
return SystemTheme.Dark;
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "Cinnamon theme detection failed", ex); }
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -247,7 +247,7 @@ public class SystemThemeService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "GTK theme file read failed", ex); }
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -317,7 +317,7 @@ public class SystemThemeService
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "KDE accent color parsing failed", ex); }
|
||||
|
||||
return new SKColor(0x21, 0x96, 0xF3);
|
||||
}
|
||||
@@ -373,7 +373,7 @@ public class SystemThemeService
|
||||
_settingsWatcher.Changed += OnSettingsChanged;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemThemeService", "Settings watcher setup failed", ex); }
|
||||
}
|
||||
|
||||
private void SetupPolling()
|
||||
|
||||
@@ -134,7 +134,7 @@ public class SystemTrayService : IDisposable
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex) { DiagnosticLog.Debug("SystemTrayService", "Tray output reading failed", ex); }
|
||||
});
|
||||
|
||||
return Task.FromResult(true);
|
||||
|
||||
Reference in New Issue
Block a user