Errore Go Concorrenza: Deadlock Ricorsivo su sync.Once
Se la funzione passata a 'once.Do(f)' richiama a sua volta 'once.Do()' sulla medesima istanza di sync.Once, l'esecuzione rimane bloccata in attesa del mutex interno già acquisito.
Categoria
Articoli tecnici organizzati per gruppo funzionale.
Se la funzione passata a 'once.Do(f)' richiama a sua volta 'once.Do()' sulla medesima istanza di sync.Once, l'esecuzione rimane bloccata in attesa del mutex interno già acquisito.
L'anomalia si manifesta quando una goroutine tenta di inviare dati su un canale senza buffer che nessun consumer sta più leggendo, rimanendo residente in memoria per l'intera durata dell'applicazione.
Un'istanza di 'recover()' posizionata nella goroutine genitrice (o nel thread principale) non può intercettare i panic delle goroutine secondarie avviate con 'go func()'; ogni goroutine deve implementare il proprio 'defer recover()'.
Inviare un valore su un canale non inizializzato ('var ch chan int; ch <- 1') non produce panic ma blocca permanentemente la goroutine; è una caratteristica usata nei costrutti 'select' ma causa gravi leak se accidentale.
All'interno di un ciclo 'for { select { case <-time.After(5*time.Minute): ... } }', ogni iterazione alloca un nuovo timer che non viene deallocato dal garbage collector fino allo scadere dei 5 minuti; si risolve riutilizzando un 'time.NewTimer()' con '.Reset()'.
Tentare di leggere dati da un canale il cui valore è 'nil' sospende la goroutine all'infinito senza mai sbloccarsi o restituire un errore.
Il metodo 'cond.Wait()' rilascia atomicamente il locker associato ('cond.L') e sospende la goroutine; se il lock non è stato preventivamente acquisito con 'cond.L.Lock()', l'invocazione di Wait() scatena un panic fatale.
L'errore viene restituito da chiamate HTTP, query a database o operazioni gRPC quando il tempo massimo allocato da 'context.WithTimeout' scade prima che l'operazione sia completata.