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 }