Příklad úniku goroutine a jak jej odladit

Když přistupuji k funkci, která kombinuje běh kusu kódu v goroutine a komunikaci / zrušení pomocí kanálů, jsem obvykle v pokušení vypadat hlouběji, protože je to skvělé místo pro zavedení goroutine úniku snadno a tyto chyby jsou docela snadno chybět i pro nezačátečníka golang vývojáře. A to jsem udělal pro tento kus kódu, který jsem našel v KUDO.

Co je to goroutinový únik?

Unikající goroutine je v podstatě typ úniku paměti. Začnete goroutinu, ale to se nikdy nezastaví, navždy zabírá paměť, kterou si rezervovala. Pro zjednodušení příkladu, který jsem poslal z KUDO, je to příklad toho, jak lze do projektu vložit goroutinu.

Co kód dělá, je to, že uvnitř goroutiny běží vynucený časový limit a periodická operace. Při každém zaškrtnutí se snažíme ověřit obchodní logiku (tvrdíme, že je něco zdravé / například připravené) - v tomto příkladu to jen simuluje toto volání spánkem a poté se vrací.

Tak kde je únik? Ve výše uvedeném zjednodušeném příkladu je časový limit pouze 1 sekunda, zatímco ověřovací operace trvá 10 sekund. To znamená, že první termín bude vynucován jako první a vrací se z `waitReady`. Asi za 9 sekund náš goroutin obdrží výsledek od ověřovatele a pokusí se zapsat do doneChan. Zápis na kanál bez vyrovnávací paměti blokuje a nikdo na tomto kanálu neposlouchá, protože jsme se již vrátili z waitReady - a tady je náš únik!

Jak zjistit, zda máte goroutinový únik?

Obecně řečeno, balíček runtime je zde váš přítel. Jedním ze způsobů je použití modulu runtime.NumGoroutine () v testu před a po vyvolání funkce waitReady. Pokud počet goroutinů před waitReady a po není stejný, máte netěsnost.

Další možností je použít knihovnu od Uber - goleak. Pokud se pustíte do toho, jak je tento implementován, spoléhá se také na runtime balíček, tentokrát přečte všechny hromádky (funkce runtime.Stack) a zavádí navíc několik výhodných metod.