Sto espandendo i miei commenti in una risposta perché penso che alcuni aspetti del problema specifico vengano trascurati o utilizzati per trarre conclusioni errate.
A questo punto, la domanda se refactoring è prematura (anche se probabilmente verrà data risposta da una specifica forma di "sì").
Il problema centrale qui è che (come notato in alcune risposte) i commenti che citate indicano fortemente che il codice ha condizioni di competizione o altri problemi di concorrenza / sincronizzazione, come discusso qui . Questi sono problemi particolarmente difficili, per diversi motivi. In primo luogo, come hai scoperto, modifiche apparentemente non correlate possono innescare il problema (anche altri bug possono avere questo effetto, ma gli errori di concorrenza quasi sempre lo fanno.) In secondo luogo, sono molto difficili da diagnosticare: il bug si manifesta spesso in un luogo che è distante nel tempo o nel codice dalla causa, e qualsiasi cosa tu faccia per diagnosticare potrebbe farla scomparire ( Heisenbugs). In terzo luogo, i test di concorrenza sono molto difficili da trovare nei test. In parte, ciò è dovuto all'esplosione combinatoria: è abbastanza male per il codice sequenziale, ma l'aggiunta dei possibili intrecci dell'esecuzione simultanea lo fa esplodere fino al punto in cui il problema sequenziale diventa insignificante in confronto. Inoltre, anche un buon caso di test può innescare il problema solo occasionalmente - Nancy Leveson ha calcolato che uno dei bug letali nel Therac 25si è verificato in 1 su circa 350 esecuzioni, ma se non si conosce quale sia il bug, o anche se ce n'è uno, non si sa quante ripetizioni rendono un test efficace. Inoltre, su questa scala è possibile solo il test automatico ed è possibile che il test driver imponga vincoli di temporizzazione sottili in modo tale da non innescare mai effettivamente il bug (Heisenbugs di nuovo).
Esistono alcuni strumenti per i test di concorrenza in alcuni ambienti, come Helgrind per il codice che utilizza pthreads POSIX, ma qui non conosciamo i dettagli. I test dovrebbero essere integrati con analisi statiche (o viceversa?), Se ci sono strumenti adatti per il tuo ambiente.
Per aggiungere alla difficoltà, i compilatori (e persino i processori, in fase di runtime) sono spesso liberi di riorganizzare il codice in modi che a volte rendono il ragionamento sulla sicurezza dei thread molto contro-intuitivo (forse il caso più noto è il doppio controllo blocca il linguaggio, sebbene alcuni ambienti (Java, C ++ ...) siano stati modificati per migliorarlo.)
Questo codice può avere un semplice problema che sta causando tutti i sintomi, ma è più probabile che tu abbia un problema sistemico che potrebbe portare i tuoi piani ad aggiungere nuove funzionalità a un arresto. Spero di averti convinto che potresti avere un grave problema tra le mani, forse anche una minaccia esistenziale per il tuo prodotto, e la prima cosa da fare è scoprire cosa sta succedendo. Se ciò rivela problemi di concorrenza, ti consiglio vivamente di risolverli prima di porre la domanda se si debba effettuare un refactoring più generale e prima di provare ad aggiungere altre funzionalità.