Open PE files with timeout in golang

Issue

I want to try open a PE file with a timeout in Go. To achieve this, I am using anonymous function while channeling out the file pointer and error. I use the select clause with a timeout case to enforce the timeout as shown below.

go func() {
    f, e := pe.Open(filePath)
    file <- f
    err <- e
}()

select {
case <-fileOpenTimeout:
    fmt.Printf("ERROR: Opening PE file timed out")
    return
case fileError := <-err:
    if fileError == nil{...}
}

This code works fine for my use case. However, this may lead to resource leakage if the file takes too long to open. How can I prevent this? Is there a better way to enforce timeout on opening the PE file?

Solution

If you have a done channel that’s passed to the anonymous func, you can use it to send a signal that you’ve ended early.

func asd() {
    fileOpenTimeout := time.After(5 * time.Second)

    type fileResponse struct {
        file *pe.File
        err error
    }

    response := make(chan fileResponse)
    done := make(chan struct{})

    go func(done <-chan struct{}) {
        f, e := pe.Open(filePath)
        r := fileResponse{
            file: f,
            err: e,
        }

        select {
        case response <- r:
            // do nothing, response sent
        case <-done:
            // clean up
            if f != nil {
                f.Close()
            }
        }
    }(done)

    select {
    case <-fileOpenTimeout:
        fmt.Printf("ERROR: Opening PE file timed out")
        close(done)
        return
    case r := <-response:
        if r.err != nil { ... }
    }
}

When the done channel is closed you will always be able to read the zero value. So your anonymous func won’t leak. There’s also a struct fileResponse that is scoped to only the function to simplify passing multiple values back from the go routine

Answered By – Zak

Answer Checked By – Timothy Miller (GoLangFix Admin)

Leave a Reply

Your email address will not be published.