非阻塞 readline 挂起时泄漏 goroutine
Leaking goroutine when a non-blocking readline hangs
假设您有这样的结构:
ch := make(chan string)
errCh := make(chan error)
go func() {
line, _, err := bufio.NewReader(r).ReadLine()
if err != nil {
errCh <- err
} else {
ch <- string(line)
}
}()
select {
case err := <-errCh:
return "", err
case line := <-ch:
return line, nil
case <-time.After(5 * time.Second):
return "", TimeoutError
}
在 5 秒超时的情况下,goroutine 挂起直到 ReadLine returns,这可能永远不会发生。我的项目是一个 long-运行 服务器,所以我不想堆积卡住的 goroutines。
ReadLine 不会 return 直到进程退出或方法读取一行。管道没有截止日期或超时机制。
如果在超时后 returns 调用 ReadLine,goroutine 将阻塞。这可以通过使用缓冲通道来解决:
ch := make(chan string, 1)
errCh := make(chan error, 1)
应用程序应调用 Wait 来清理与命令关联的资源。 goroutine 是调用它的好地方:
go func() {
line, _, err := bufio.NewReader(r).ReadLine()
if err != nil {
errCh <- err
} else {
ch <- string(line)
}
cmd.Wait() // <-- add this line
}()
这将导致 goroutine 阻塞,而这正是您要避免的事情。替代方案是应用程序泄漏每个命令的资源。
假设您有这样的结构:
ch := make(chan string)
errCh := make(chan error)
go func() {
line, _, err := bufio.NewReader(r).ReadLine()
if err != nil {
errCh <- err
} else {
ch <- string(line)
}
}()
select {
case err := <-errCh:
return "", err
case line := <-ch:
return line, nil
case <-time.After(5 * time.Second):
return "", TimeoutError
}
在 5 秒超时的情况下,goroutine 挂起直到 ReadLine returns,这可能永远不会发生。我的项目是一个 long-运行 服务器,所以我不想堆积卡住的 goroutines。
ReadLine 不会 return 直到进程退出或方法读取一行。管道没有截止日期或超时机制。
如果在超时后 returns 调用 ReadLine,goroutine 将阻塞。这可以通过使用缓冲通道来解决:
ch := make(chan string, 1)
errCh := make(chan error, 1)
应用程序应调用 Wait 来清理与命令关联的资源。 goroutine 是调用它的好地方:
go func() {
line, _, err := bufio.NewReader(r).ReadLine()
if err != nil {
errCh <- err
} else {
ch <- string(line)
}
cmd.Wait() // <-- add this line
}()
这将导致 goroutine 阻塞,而这正是您要避免的事情。替代方案是应用程序泄漏每个命令的资源。