Паника по блокировке файлов Golang flock: ошибка во время выполнения: неверный адрес памяти или разыменование нулевого указателя

У меня есть программа go, которая изменяет мой файл конфигурации. Я пытаюсь создать блокировку файла из функции main(), но panic: runtime error: invalid memory address or nil pointer dereference ошибка. Без блокировки программа работает нормально, как и ожидалось. Кусок кода, который выдает исключение

lockProgram, err := os.Create("/var/.daemon.lock")
defer lockProgram.Close()
CheckForError(err)
GetLock(lockProgram, syscall.LOCK_EX)
defer UngetLock(lockProgram)

// Это в отдельном пакете

func CheckForError(e error) {
    if e != nil {
        Error.Println(e)
        panic(e)
    }
}

func GetLock(file *os.File, locktype int )  {
    fmt.Println("Acquiring lock on ", file.Name())
    syscall.Flock(int(file.Fd()), locktype)
    fmt.Println("Acquired filelock on ", file.Name())
}
func UngetLock(file *os.File)  {
    syscall.Flock(int(file.Fd()), syscall.LOCK_UN);
}

Это же flock работает, когда я вызываю его в моем файле конфигурации, но из другого пакета, а не из основного пакета, но выдает ту же ошибку при попытке установить блокировку из основного пакета. Пожалуйста, помогите мне выяснить, что я делаю здесь не так.

1 ответ

Решение

Когда ошибка возникает при создании блокировки, lockProgram будет nil, Это вызовет последующий (отложенный) вызов lockProgram.Close() терпеть неудачу.

Обратите внимание, что когда вы паникуете (как в вашем CheckForError функция), отложенные вызовы методов по-прежнему будут выполняться. Это подробно объясняется в этой статье блога (выделено мной):

Паника - это встроенная функция, которая останавливает обычный поток контроля и начинает паниковать. Когда функция F вызывает панику, выполнение F останавливается, все отложенные функции в F выполняются нормально, а затем F возвращается к своему вызывающему. Для вызывающего абонента F ведет себя как призыв к панике. Процесс продолжается вверх по стеку до тех пор, пока не будут возвращены все функции в текущей процедуре, после чего программа вылетает.

Решение. Сначала проверьте ошибки, а затем отложите Close() вызов:

lockProgram, err := os.Create("/var/.daemon.lock")
CheckForError(err)
defer lockProgram.Close()
Другие вопросы по тегам