github.com/demonoid81/containerd@v1.3.4/runtime/v2/binary.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 "bytes" 21 "context" 22 "io" 23 "os" 24 gruntime "runtime" 25 "strings" 26 27 "github.com/containerd/containerd/events/exchange" 28 "github.com/containerd/containerd/log" 29 "github.com/containerd/containerd/runtime" 30 client "github.com/containerd/containerd/runtime/v2/shim" 31 "github.com/containerd/containerd/runtime/v2/task" 32 "github.com/containerd/ttrpc" 33 "github.com/gogo/protobuf/types" 34 "github.com/pkg/errors" 35 "github.com/sirupsen/logrus" 36 ) 37 38 func shimBinary(ctx context.Context, bundle *Bundle, runtime, containerdAddress string, containerdTTRPCAddress string, events *exchange.Exchange, rt *runtime.TaskList) *binary { 39 return &binary{ 40 bundle: bundle, 41 runtime: runtime, 42 containerdAddress: containerdAddress, 43 containerdTTRPCAddress: containerdTTRPCAddress, 44 events: events, 45 rtTasks: rt, 46 } 47 } 48 49 type binary struct { 50 runtime string 51 containerdAddress string 52 containerdTTRPCAddress string 53 bundle *Bundle 54 events *exchange.Exchange 55 rtTasks *runtime.TaskList 56 } 57 58 func (b *binary) Start(ctx context.Context, opts *types.Any, onClose func()) (_ *shim, err error) { 59 args := []string{"-id", b.bundle.ID} 60 if logrus.GetLevel() == logrus.DebugLevel { 61 args = append(args, "-debug") 62 } 63 args = append(args, "start") 64 65 cmd, err := client.Command( 66 ctx, 67 b.runtime, 68 b.containerdAddress, 69 b.containerdTTRPCAddress, 70 b.bundle.Path, 71 opts, 72 args..., 73 ) 74 if err != nil { 75 return nil, err 76 } 77 f, err := openShimLog(ctx, b.bundle, client.AnonDialer) 78 if err != nil { 79 return nil, errors.Wrap(err, "open shim log pipe") 80 } 81 defer func() { 82 if err != nil { 83 f.Close() 84 } 85 }() 86 // open the log pipe and block until the writer is ready 87 // this helps with synchronization of the shim 88 // copy the shim's logs to containerd's output 89 go func() { 90 defer f.Close() 91 _, err := io.Copy(os.Stderr, f) 92 err = checkCopyShimLogError(ctx, err) 93 if err != nil { 94 log.G(ctx).WithError(err).Error("copy shim log") 95 } 96 }() 97 out, err := cmd.CombinedOutput() 98 if err != nil { 99 return nil, errors.Wrapf(err, "%s", out) 100 } 101 address := strings.TrimSpace(string(out)) 102 conn, err := client.Connect(address, client.AnonDialer) 103 if err != nil { 104 return nil, err 105 } 106 client := ttrpc.NewClient(conn, ttrpc.WithOnClose(onClose)) 107 return &shim{ 108 bundle: b.bundle, 109 client: client, 110 task: task.NewTaskClient(client), 111 events: b.events, 112 rtTasks: b.rtTasks, 113 }, nil 114 } 115 116 func (b *binary) Delete(ctx context.Context) (*runtime.Exit, error) { 117 log.G(ctx).Info("cleaning up dead shim") 118 119 // Windows cannot delete the current working directory while an 120 // executable is in use with it. For the cleanup case we invoke with the 121 // default work dir and forward the bundle path on the cmdline. 122 var bundlePath string 123 if gruntime.GOOS != "windows" { 124 bundlePath = b.bundle.Path 125 } 126 127 cmd, err := client.Command(ctx, 128 b.runtime, 129 b.containerdAddress, 130 b.containerdTTRPCAddress, 131 bundlePath, 132 nil, 133 "-id", b.bundle.ID, 134 "-bundle", b.bundle.Path, 135 "delete") 136 if err != nil { 137 return nil, err 138 } 139 var ( 140 out = bytes.NewBuffer(nil) 141 errb = bytes.NewBuffer(nil) 142 ) 143 cmd.Stdout = out 144 cmd.Stderr = errb 145 if err := cmd.Run(); err != nil { 146 return nil, errors.Wrapf(err, "%s", errb.String()) 147 } 148 s := errb.String() 149 if s != "" { 150 log.G(ctx).Warnf("cleanup warnings %s", s) 151 } 152 var response task.DeleteResponse 153 if err := response.Unmarshal(out.Bytes()); err != nil { 154 return nil, err 155 } 156 if err := b.bundle.Delete(); err != nil { 157 return nil, err 158 } 159 return &runtime.Exit{ 160 Status: response.ExitStatus, 161 Timestamp: response.ExitedAt, 162 Pid: response.Pid, 163 }, nil 164 }