From bee17a7fc6dabef4c38160b4a2c2ff9e091f510b Mon Sep 17 00:00:00 2001 From: duffyduck Date: Mon, 8 Jun 2026 12:14:23 +0200 Subject: [PATCH] Make local sync re-entrancy guard atomic Der Schutz gegen gleichzeitige Syncs (manuell vs. Auto-Sync-Timer) war ein nicht-atomares pruefen-und-setzen auf einem volatile bool. Zwischen Pruefung und Setzen konnten ein UI-Klick und der Timer-Thread beide durchrutschen und zwei Syncs gleichzeitig starten. Jetzt per Interlocked.CompareExchange atomar. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 4 ++++ src/StarfaceOutlookSync/UI/MainForm.cs | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4620b38..34c23d4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,10 @@ Versionsschema ist `x.x.x.x` (siehe `release.sh`). ### Geaendert +- **Doppelte Syncs verhindert (lokal).** Der Schutz gegen gleichzeitig laufende + Syncs (manuell + Auto-Sync-Timer) ist jetzt atomar (`Interlocked`) statt eines + nicht-atomaren `volatile bool`, bei dem beide in einem Zeitfenster + durchrutschen konnten. - **Ein-Richtungs-Modi sind jetzt echtes "Ersetzen".** Outlook->Starface macht das Starface-Adressbuch zu einer exakten Kopie von Outlook: Kontakte, die nur in Starface existieren (kein Pendant in Outlook), werden geloescht. diff --git a/src/StarfaceOutlookSync/UI/MainForm.cs b/src/StarfaceOutlookSync/UI/MainForm.cs index a759f699..4337e1da 100644 --- a/src/StarfaceOutlookSync/UI/MainForm.cs +++ b/src/StarfaceOutlookSync/UI/MainForm.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Timers; using System.Windows.Forms; @@ -22,7 +23,9 @@ namespace StarfaceOutlookSync.UI private StatusStrip _statusBar; private ToolStripStatusLabel _statusLabel; private Timer _autoSyncTimer; - private volatile bool _syncRunning = false; + // 0 = frei, 1 = Sync laeuft. Per Interlocked atomar geschaltet, damit + // ein manueller Sync und der Auto-Sync-Timer nicht gleichzeitig starten. + private int _syncRunning = 0; public MainForm() { @@ -337,13 +340,14 @@ namespace StarfaceOutlookSync.UI private async Task RunSync(SyncProfile profile) { - if (_syncRunning) + // Atomar pruefen-und-setzen: verhindert, dass manueller Sync und + // Auto-Sync-Timer gleichzeitig denselben/einen Sync starten. + if (Interlocked.CompareExchange(ref _syncRunning, 1, 0) != 0) { SetStatus("Sync laeuft bereits, bitte warten..."); return; } - _syncRunning = true; try { SetStatus($"Synchronisiere '{profile.Name}'..."); @@ -368,7 +372,7 @@ namespace StarfaceOutlookSync.UI } finally { - _syncRunning = false; + Interlocked.Exchange(ref _syncRunning, 0); } }