Golang flock filelocking throwing panic: runtime error: invalid memory address or nil pointer dereference

huangapple go评论81阅读模式
英文:

Golang flock filelocking throwing panic: runtime error: invalid memory address or nil pointer dereference

问题

我有一个修改配置文件的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函数来锁定配置文件时,它是正常工作的,但是当我尝试在主包内部放置锁时,它抛出相同的错误。请帮助我找出我在这里做错了什么。

英文:

I have a go program that modifies my configuration file. I am trying to create a filelock from within the main() function, but it is throwing a panic: runtime error: invalid memory address or nil pointer dereference error. Without the lock, the program is working fine as expected. The piece of code that throws exception is

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

//This is in a separate package

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);
}

This same flock is working when I call it on my configuration file, but from a different package, not main package, but throws the same error when I try to put lock from within the main package. Please help me in finding out what am I doing wrong here.

答案1

得分: 1

当在创建锁时发生错误时,lockProgram 将为 nil。这将导致随后的(延迟的)lockProgram.Close() 调用失败。

请注意,当发生 panic(例如在你的 CheckForError 函数中),延迟的方法调用仍然会执行。这在 这篇博文 中有详细解释(强调是我的):

>Panic 是一个内置函数,它停止正常的控制流程并开始 panic。当函数 F 调用 panic 时,F 的执行停止,F 中的任何延迟函数都会正常执行,然后 F 返回给它的调用者。对于调用者来说,F 的行为就像调用 panic 一样。这个过程一直沿着调用栈向上进行,直到当前 goroutine 中的所有函数都返回,此时程序崩溃。

解决方案:先检查错误,然后延迟调用 Close()

lockProgram, err := os.Create("/var/.daemon.lock")
CheckForError(err)
defer lockProgram.Close()
英文:

When an error occurs while creating the lock, lockProgram will be nil. This will cause the subsequent (deferred) call to lockProgram.Close() to fail.

Note that when you're panicking (like in your CheckForError function), deferred method calls will still be executed. This is explained in detail in this blog article (emphasis mine):

>Panic is a built-in function that stops the ordinary flow of control and begins panicking. When the function F calls panic, execution of F stops, any deferred functions in F are executed normally, and then F returns to its caller. To the caller, F then behaves like a call to panic. The process continues up the stack until all functions in the current goroutine have returned, at which point the program crashes.

Solution: Check for errors first, and then defer the Close() call:

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

huangapple
  • 本文由 发表于 2016年1月11日 04:31:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/34710460.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定