github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/runtime/v2/shim_windows.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package v2
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"io"
    23  	"net"
    24  	"os"
    25  	"sync"
    26  	"time"
    27  
    28  	"github.com/containerd/containerd/namespaces"
    29  	"github.com/pkg/errors"
    30  )
    31  
    32  type deferredPipeConnection struct {
    33  	ctx context.Context
    34  
    35  	wg   sync.WaitGroup
    36  	once sync.Once
    37  
    38  	c      net.Conn
    39  	conerr error
    40  }
    41  
    42  func (dpc *deferredPipeConnection) Read(p []byte) (n int, err error) {
    43  	if dpc.c == nil {
    44  		dpc.wg.Wait()
    45  		if dpc.c == nil {
    46  			return 0, dpc.conerr
    47  		}
    48  	}
    49  	return dpc.c.Read(p)
    50  }
    51  func (dpc *deferredPipeConnection) Close() error {
    52  	var err error
    53  	dpc.once.Do(func() {
    54  		dpc.wg.Wait()
    55  		if dpc.c != nil {
    56  			err = dpc.c.Close()
    57  		} else if dpc.conerr != nil {
    58  			err = dpc.conerr
    59  		}
    60  	})
    61  	return err
    62  }
    63  
    64  // openShimLog on Windows acts as the client of the log pipe. In this way the
    65  // containerd daemon can reconnect to the shim log stream if it is restarted.
    66  func openShimLog(ctx context.Context, bundle *Bundle, dialer func(string, time.Duration) (net.Conn, error)) (io.ReadCloser, error) {
    67  	ns, err := namespaces.NamespaceRequired(ctx)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	dpc := &deferredPipeConnection{
    72  		ctx: ctx,
    73  	}
    74  	dpc.wg.Add(1)
    75  	go func() {
    76  		c, conerr := dialer(
    77  			fmt.Sprintf("\\\\.\\pipe\\containerd-shim-%s-%s-log", ns, bundle.ID),
    78  			time.Second*10,
    79  		)
    80  		if conerr != nil {
    81  			dpc.conerr = errors.Wrap(conerr, "failed to connect to shim log")
    82  		}
    83  		dpc.c = c
    84  		dpc.wg.Done()
    85  	}()
    86  	return dpc, nil
    87  }
    88  
    89  func checkCopyShimLogError(ctx context.Context, err error) error {
    90  	// When using a multi-container shim the 2nd to Nth container in the
    91  	// shim will not have a separate log pipe. Ignore the failure log
    92  	// message here when the shim connect times out.
    93  	if errors.Is(err, os.ErrNotExist) {
    94  		return nil
    95  	}
    96  	return err
    97  }