Я работаю с собственным бинарным файлом Linux C, который имеет довольно дорогой вызов инициализации, который я хотел бы выполнить один раз при запуске приложения. Этот вызов должен открыть кучу внутренних дескрипторов файлов для последующего использования. Когда я вызываю эту дорогостоящую C-функцию инициализации из Go, она успешно завершается и правильно открывает файлы, но эти дескрипторы открыты только на время вызова C-функции! Это означает, что когда я вызываю последовательные функции C для одной и той же библиотеки из Go, дескрипторы файлов больше не открываются, и вызовы завершаются ошибкой. Я проверил это с помощью команды lsof. Интересно, что когда вызов инициализации, а также вызовы последующего поведения объединяются в одну функцию C, которая затем вызывается из Go, файлы открываются и остаются открытыми, что позволяет успешно завершить все желаемые функции.
Есть ли какое-то недокументированное поведение cgo, которое «очищает», завершает работу или даже приводит к утечке файловых дескрипторов или других ресурсов с состоянием между несколькими вызовами функций C из Go? Если да, можно ли настроить это поведение? У нас нет доступа к исходному коду этой библиотеки.
Кроме того, я убедился, что это не связано с локальным хранилищем потока. Вызов runtime.LockOSThread()
не имеет никакого эффекта, и мы убедились, что файлы закрываются после того, как управление возвращается от C обратно к вызывающему коду Go.
Вот пример кода Go, который я хотел бы написать:
// Go code:
func main() {
C.Initialize()
C.do_stuff() // internal state is already cleaned up! This call fails as a result. :(
}
Вот пример функции C, которая одновременно вызывает инициализацию и поведение. Эта «обертывающая» функция вызывается из Go:
// C code:
void DoEverything(void)
{
Initialize();
do_stuff(); // succeeds because all internal state is intact (not cleaned up).
}