Пример утечки горутина и как ее отладить

Когда я подхожу к функции, которая сочетает в себе выполнение части кода в программе и связь / отмену с использованием каналов, я обычно испытываю желание заглянуть глубже, поскольку это отличное место для довольно простого введения утечки из программы и эти ошибки довольно легко исправить. пропустить даже для начинающего разработчика golang. И это то, что я сделал для этого куска кода, который я нашел в KUDO.

Что такое утечка горутина?

Утечка goroutine - это тип утечки памяти. Вы запускаете программу, но она никогда не закончится, навсегда занимая зарезервированную память. Чтобы немного упростить пример, который я выложил из KUDO, это пример того, как можно внести утечку горутина в их проект.

Код делает то, что в goroutine выполняется принудительное время ожидания и периодическая операция. Каждый тик мы пытаемся проверить некоторую бизнес-логику (например, утверждать, что что-то здоровое / готово) - в этом примере он просто имитирует этот вызов, спя и затем возвращаясь.

Так где же утечка? В приведенном выше упрощенном примере время ожидания составляет всего 1 секунду, а операция проверки занимает 10 секунд. Это означает, что крайний срок будет соблюдаться первым, возвращаясь из `waitReady`. Приблизительно через 9 секунд наша программа получает результат от верификатора и пытается записать в doneChan. Запись в небуферизованный канал блокируется, и никто не слушает этот канал, потому что мы уже вернулись из waitReady - и вот наша утечка!

Как узнать, есть ли у вас утечка горутина?

Вообще говоря, пакет `runtime` здесь ваш друг. Одним из способов является использование runtime.NumGoroutine () в тесте до и после вызова функции waitReady. Если количество процедур до waitReady и after не совпадает, у вас есть утечка.

Другой вариант - использовать библиотеку от Uber - goleak. Если вы углубитесь в то, как это реализовано, он также полагается на пакет времени выполнения, на этот раз он читает все стеки (функция runtime.Stack) и вводит несколько удобных методов поверх этого.