浏览代码

Fix unhandled panics during animated images processing

DarthSim 5 年之前
父节点
当前提交
13546aa405
共有 2 个文件被更改,包括 45 次插入9 次删除
  1. 39 0
      panic_group.go
  2. 6 9
      process.go

+ 39 - 0
panic_group.go

@@ -0,0 +1,39 @@
+package main
+
+import "sync"
+
+type panicGroup struct {
+	wg      sync.WaitGroup
+	errOnce sync.Once
+	err     error
+}
+
+func (g *panicGroup) Wait() error {
+	g.wg.Wait()
+	return g.err
+}
+
+func (g *panicGroup) Go(f func() error) {
+	g.wg.Add(1)
+
+	go func() {
+		defer g.wg.Done()
+		defer func() {
+			if r := recover(); r != nil {
+				if err, ok := r.(error); ok {
+					g.errOnce.Do(func() {
+						g.err = err
+					})
+				} else {
+					panic(r)
+				}
+			}
+		}()
+
+		if err := f(); err != nil {
+			g.errOnce.Do(func() {
+				g.err = err
+			})
+		}
+	}()
+}

+ 6 - 9
process.go

@@ -8,7 +8,6 @@ import (
 	"runtime"
 	"runtime"
 
 
 	"github.com/imgproxy/imgproxy/v2/imagemeta"
 	"github.com/imgproxy/imgproxy/v2/imagemeta"
-	"golang.org/x/sync/errgroup"
 )
 )
 
 
 const msgSmartCropNotSupported = "Smart crop is not supported by used version of libvips"
 const msgSmartCropNotSupported = "Smart crop is not supported by used version of libvips"
@@ -546,23 +545,21 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
 	po.Watermark.Enabled = false
 	po.Watermark.Enabled = false
 	defer func() { po.Watermark.Enabled = watermarkEnabled }()
 	defer func() { po.Watermark.Enabled = watermarkEnabled }()
 
 
-	var errg errgroup.Group
+	var errg panicGroup
 
 
 	for i := 0; i < framesCount; i++ {
 	for i := 0; i < framesCount; i++ {
 		ind := i
 		ind := i
 		errg.Go(func() error {
 		errg.Go(func() error {
-			frame := new(vipsImage)
+			frames[ind] = new(vipsImage)
 
 
-			if err = img.Extract(frame, 0, ind*frameHeight, imgWidth, frameHeight); err != nil {
-				return err
+			if ferr := img.Extract(frames[ind], 0, ind*frameHeight, imgWidth, frameHeight); ferr != nil {
+				return ferr
 			}
 			}
 
 
-			if err = transformImage(ctx, frame, nil, po, imgtype); err != nil {
-				return err
+			if ferr := transformImage(ctx, frames[ind], nil, po, imgtype); ferr != nil {
+				return ferr
 			}
 			}
 
 
-			frames[ind] = frame
-
 			return nil
 			return nil
 		})
 		})
 	}
 	}