@@ -186,8 +186,32 @@ func (u *unpacker) unpack(ctx context.Context, config ocispec.Descriptor, layers
186186 return nil
187187}
188188
189- func (u * unpacker ) handlerWrapper (uctx context.Context , unpacks * int32 ) (func (images.Handler ) images.Handler , * errgroup.Group ) {
190- eg , uctx := errgroup .WithContext (uctx )
189+ type errGroup struct {
190+ * errgroup.Group
191+ cancel context.CancelFunc
192+ }
193+
194+ func newErrGroup (ctx context.Context ) (* errGroup , context.Context ) {
195+ ctx , cancel := context .WithCancel (ctx )
196+ eg , ctx := errgroup .WithContext (ctx )
197+ return & errGroup {
198+ Group : eg ,
199+ cancel : cancel ,
200+ }, ctx
201+ }
202+
203+ func (e * errGroup ) Cancel () {
204+ e .cancel ()
205+ }
206+
207+ func (e * errGroup ) Wait () error {
208+ err := e .Group .Wait ()
209+ e .cancel ()
210+ return err
211+ }
212+
213+ func (u * unpacker ) handlerWrapper (uctx context.Context , unpacks * int32 ) (func (images.Handler ) images.Handler , * errGroup ) {
214+ eg , uctx := newErrGroup (uctx )
191215 return func (f images.Handler ) images.Handler {
192216 var (
193217 lock sync.Mutex
@@ -234,7 +258,19 @@ func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(im
234258 update := ! schema1
235259 lock .Unlock ()
236260 if update {
237- u .updateCh <- desc
261+ select {
262+ case <- uctx .Done ():
263+ // Do not send update if unpacker is not running.
264+ default :
265+ select {
266+ case u .updateCh <- desc :
267+ case <- uctx .Done ():
268+ // Do not send update if unpacker is not running.
269+ }
270+ }
271+ // Checking ctx.Done() prevents the case that unpacker
272+ // exits unexpectedly, but update continues to be generated,
273+ // and eventually fills up updateCh and blocks forever.
238274 }
239275 }
240276 return children , nil
0 commit comments