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?
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