为什么在for循环中调用ioutil.ReadFile()后会挂起?

I wrote a function that converts an image to a base64 string:

func getBase64Screenshot() string {
    // Image name
    imageName := "Screenshots/screenshot.png"

    imageFileBytes, err := ioutil.ReadFile(imageName)
    handleError(err)

    // Converts file to base64 string
    encoded := base64.StdEncoding.EncodeToString(imageFileBytes)

    return encoded
}

The above function is called in a for loop, however after some iterations of the for loop, the program just hangs at the line imageFileBytes, err := ioutil.ReadFile(imageName) (it doesn't throw an error, it just stops running and stalls).

I ran some experiments and found that if I used a smaller image, it would make it through ~5 iterations of the for loop before stalling, however if I screenshot my entire screen it would only make it through the first iteration of the for loop before stalling.

My question is this: What is causing the program to hang, and is there anything I can do to prevent it from hanging?

Thanks!

Debug your code.


Try this and let me know if this works for you too:
This works like a charm for me on Linux:

package main

import (
    "encoding/base64"
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(getBase64Screenshot()[:10])
    }
}
func getBase64Screenshot() string {
    buf, err := ioutil.ReadFile(os.Args[0])
    if err != nil {
        log.Fatal(err)
    }
    encoded := base64.StdEncoding.EncodeToString(buf)
    return encoded
}

Output:

time go run main.go
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ

real    0m0.340s
user    0m0.369s
sys     0m0.128s

One way to debug the issue is to send a SIGABRT to your running program (when hanging) in order to causes the program to exit with a stack dump.

kill -ABRT <pid>
# or CTRL+Pause on Windows.

Then you will see where the program is hang, and if it is actually related to your function or not.

Hey guys I was able to fix the issue.

You see, initially the function getBase64Screenshot() that I wrote above was being called every 10 seconds inside of a goroutine.

To fix the issue I refactored my code to eliminate the goroutine and instead call getBase64Screenshot() inside of an infinite loop:

for {
        getBase64Screenshot()
        time.Sleep(timedelayMilliseconds * time.Millisecond)
    }

I've tested the above code by running it for over 30 minutes with very large screenshots (>1MB in size), and it has never crashed or stalled.

Though I've fixed the issue I encountered, I haven't been able to figure out what exactly caused it in the first place. I welcome any theories as to why my original code above stalled.