GoLang CGO обрабатывает файлы

Я работаю с нативным двоичным файлом Linux, который имеет довольно дорогой вызов инициализации, который я хотел бы выполнить один раз при запуске приложения. Этот вызов должен открыть кучу файловых дескрипторов для последующего использования. Когда я вызываю эту дорогостоящую функцию 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).
}

1 ответ

Решение

Хорошо, это немного смущает, но я понял это. Сразу после вызова initialize() я вызывал defer close (), но на самом деле это было defer fmt.Println(close()). Поскольку аргументы для отложенных функций разрешаются немедленно (не откладывается), функция close была вызвана до того, как мы могли вызвать любое другое поведение. Блог golang четко объясняет разрешение аргументов для отложенных вызовов функций.

Другие вопросы по тегам