Как стать автором
Обновить

Комментарии 6

Подробности того, как ловил ошибку, как раз и есть самое интересное.

А ещё это показательный пример работы с нейронкой (grok, в моём случае). Если скормить ей кусок кода из статьи и попросить найти проблемы, то она напишет кучу воды про обработку ошибок и т.п., но не про это. А если прямо спросить про гонку данных, то распишет во всех подробностях. Вот поэтому нейронки не заменят программистов, по крайней мере не в близкой перспективе. Потому что основной скилл хорошего программиста - это вовсе не умение что-то там написать. Это понимание того, что надо написать, в какую сторону копать и какие вопросы спрашивать. В том числе и у нейронки.

Подробности того, как ловил ошибку, как раз и есть самое интересное.

Понятное дело. Только пересказать это невозможно.

Сначала пытался отсекать лишнее. Но только беда в том, что как я не упрощал этот код, плавающая ошибка не уходила (может это и к лучшему, иногда бывает так, что плавающая ошибка всё время лезет, пока ей не займешься. А потом прячется).

Выяснил, что если вставить задержку в гороутинку, которая делает ServeTLS, то ошибка выскакивает всегда. А если в другую, то и вовсе не выскакивает.

С самого начала было понятно, что это какая-то гонка. Но сколько я ее не искал, найти не мог.

Посмотрел в код стандартной библиотеки, не делает ли она чего в фоне. Вроде нет, но она сложная, её сложно читать, поэтому 100% не было.

Возникла гипотеза, что может если создавать сервер и сразу делать к нему запрос, возможно внутри самого сервера что-то не успело еще проинициализироваться, и слишком ранние запросы сервер отрабатывает неправильно (в боевых-то условиях так редко бывает и особенно не заметно). Написал соответствующий тест, погонял - все ОК. Догадка не подтвердилась.

Поискал, где запускаются гороутинки в net.http и crypto.tls. Сравнил между версиями go. Никакой значимой разницы не обнаружил.

Потом пришла догадка, что может Serve и ServeTLS и не стоило бы одновременно запускать. Посмотрел еще раз попристальнее в код net.http - вижу, что они там на старте чего-то в Server накручивают под себя, в его глубинах. Так догадка перерасла в уверенность.

Ну а дальше просто, разбил Server на два, проверил - работает. Убрал всю вставленную в процессе отладки отладочную печать, еще раз проверил - работает. Ну и туды его, в commit :)

А go test -race не указывал на проблемы?

Нет, не указывал.

Там вроде есть какая-то синхронизация, в инициализации этого самого http.Server. Т.е., там не классическая гонка, а "кто первый встал, того и тапки". Т.е., в зависимости от того, какая функция первая успеет прошмыгнуть в критическую секцию, результат получится разный. Но консистентный. Но при этом не подходящий для другой функции.

Да не похоже на гонку. Тем более тогда бы ломался бы не "всегда ServeTLS". "unexpected EOF" в HTTP намекает на то, что сервер некорректные данные отдаёт, например в TLS соединении - обычные незашифрованные.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации