| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -7,6 +7,7 @@ import (
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"io"
 | 
					 | 
					 | 
					 | 
						"io"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"sync"
 | 
					 | 
					 | 
					 | 
						"sync"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"sync/atomic"
 | 
					 | 
					 | 
					 | 
						"sync/atomic"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						"time"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						controllerapi "github.com/docker/buildx/controller/pb"
 | 
					 | 
					 | 
					 | 
						controllerapi "github.com/docker/buildx/controller/pb"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						"github.com/moby/buildkit/client"
 | 
					 | 
					 | 
					 | 
						"github.com/moby/buildkit/client"
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -74,9 +75,11 @@ func getResultAt(ctx context.Context, c *client.Client, solveOpt client.SolveOpt
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						go func() {
 | 
					 | 
					 | 
					 | 
						go func() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							solveOpt := solveOpt
 | 
					 | 
					 | 
					 | 
							solveOpt := solveOpt
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							solveOpt.Ref = ""
 | 
					 | 
					 | 
					 | 
							solveOpt.Ref = ""
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							buildDoneCh := make(chan struct{})
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							_, err := c.Build(context.Background(), solveOpt, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
 | 
					 | 
					 | 
					 | 
							_, err := c.Build(context.Background(), solveOpt, "buildx", func(ctx context.Context, c gateway.Client) (*gateway.Result, error) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								ctx, cancel := context.WithCancel(ctx)
 | 
					 | 
					 | 
					 | 
								doneErr := errors.Errorf("done")
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								defer cancel()
 | 
					 | 
					 | 
					 | 
								ctx, cancel := context.WithCancelCause(ctx)
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								defer cancel(doneErr)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								resultCtx := ResultContext{}
 | 
					 | 
					 | 
					 | 
								resultCtx := ResultContext{}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								res2, err := c.Solve(ctx, gateway.SolveRequest{
 | 
					 | 
					 | 
					 | 
								res2, err := c.Solve(ctx, gateway.SolveRequest{
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									Evaluate:   true,
 | 
					 | 
					 | 
					 | 
									Evaluate:   true,
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -94,15 +97,28 @@ func getResultAt(ctx context.Context, c *client.Client, solveOpt client.SolveOpt
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								resultCtx.res = res2
 | 
					 | 
					 | 
					 | 
								resultCtx.res = res2
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								resultCtx.gwClient = c
 | 
					 | 
					 | 
					 | 
								resultCtx.gwClient = c
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								resultCtx.gwCtx = ctx
 | 
					 | 
					 | 
					 | 
								resultCtx.gwCtx = ctx
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								resultCtx.gwDone = cancel
 | 
					 | 
					 | 
					 | 
								resultCtx.gwDone = func() {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									cancel(doneErr)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									// wait for Build() completion(or timeout) to ensure the Build's finalizing and avoiding an error "context canceled"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									select {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									case <-buildDoneCh:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									case <-time.After(5 * time.Second):
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								select {
 | 
					 | 
					 | 
					 | 
								select {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case resultCtxCh <- &resultCtx:
 | 
					 | 
					 | 
					 | 
								case resultCtxCh <- &resultCtx:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								case <-ctx.Done():
 | 
					 | 
					 | 
					 | 
								case <-ctx.Done():
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									return nil, ctx.Err()
 | 
					 | 
					 | 
					 | 
									return nil, ctx.Err()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								}
 | 
					 | 
					 | 
					 | 
								}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// wait for cleanup or cancel
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								<-ctx.Done()
 | 
					 | 
					 | 
					 | 
								<-ctx.Done()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if context.Cause(ctx) != doneErr { // doneErr is not an error.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									return nil, ctx.Err()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return nil, nil
 | 
					 | 
					 | 
					 | 
								return nil, nil
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							}, ch)
 | 
					 | 
					 | 
					 | 
							}, ch)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							close(buildDoneCh)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if err != nil {
 | 
					 | 
					 | 
					 | 
							if err != nil {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								errCh <- err
 | 
					 | 
					 | 
					 | 
								errCh <- err
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							}
 | 
					 | 
					 | 
					 | 
							}
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
 
 |