Fixed leak of goroutine and channel in Video.cleanup()

This commit is contained in:
Giuseppe Coviello 2024-01-23 13:37:58 -05:00
parent cf92b10b6b
commit afcc49ec6c

View file

@ -27,6 +27,9 @@ type Video struct {
metadata map[string]string // Video metadata.
pipe io.ReadCloser // Stdout pipe for ffmpeg process.
cmd *exec.Cmd // ffmpeg command.
closeCleanupChan chan struct{} // exit from cleanup goroutine to avoid chan and goroutine leak
cleanupClosed bool
}
func (video *Video) FileName() string {
@ -150,6 +153,8 @@ func NewVideoStreams(filename string) ([]*Video, error) {
stream: i,
hasstreams: hasstream,
metadata: data,
closeCleanupChan: make(chan struct{}, 1),
}
video.addVideoData(data)
@ -384,6 +389,11 @@ func (video *Video) ReadFrames(n ...int) ([]*image.RGBA, error) {
// Closes the pipe and stops the ffmpeg process.
func (video *Video) Close() {
if !video.cleanupClosed {
video.cleanupClosed = true
video.closeCleanupChan <- struct{}{}
close(video.closeCleanupChan)
}
if video.pipe != nil {
video.pipe.Close()
}
@ -398,13 +408,18 @@ func (video *Video) cleanup() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
if video.pipe != nil {
video.pipe.Close()
select {
case <-c:
if video.pipe != nil {
video.pipe.Close()
}
if video.cmd != nil {
video.cmd.Process.Kill()
}
os.Exit(1)
case <-video.closeCleanupChan:
signal.Stop(c)
close(c)
}
if video.cmd != nil {
video.cmd.Process.Kill()
}
os.Exit(1)
}()
}