github.com/demonoid81/containerd@v1.3.4/cmd/containerd-stress/exec_worker.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 main 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 "syscall" 24 "time" 25 26 "github.com/containerd/containerd" 27 "github.com/containerd/containerd/cio" 28 "github.com/containerd/containerd/oci" 29 specs "github.com/opencontainers/runtime-spec/specs-go" 30 "github.com/sirupsen/logrus" 31 ) 32 33 type execWorker struct { 34 worker 35 } 36 37 func (w *execWorker) exec(ctx, tctx context.Context) { 38 defer func() { 39 w.wg.Done() 40 logrus.Infof("worker %d finished", w.id) 41 }() 42 id := fmt.Sprintf("exec-container-%d", w.id) 43 c, err := w.client.NewContainer(ctx, id, 44 containerd.WithNewSnapshot(id, w.image), 45 containerd.WithNewSpec(oci.WithImageConfig(w.image), oci.WithUsername("games"), oci.WithProcessArgs("sleep", "30d")), 46 ) 47 if err != nil { 48 logrus.WithError(err).Error("create exec container") 49 return 50 } 51 defer c.Delete(ctx, containerd.WithSnapshotCleanup) 52 53 task, err := c.NewTask(ctx, cio.NullIO) 54 if err != nil { 55 logrus.WithError(err).Error("create exec container's task") 56 return 57 } 58 defer task.Delete(ctx, containerd.WithProcessKill) 59 60 statusC, err := task.Wait(ctx) 61 if err != nil { 62 logrus.WithError(err).Error("wait exec container's task") 63 return 64 } 65 spec, err := c.Spec(ctx) 66 if err != nil { 67 logrus.WithError(err).Error("failed to get spec") 68 return 69 } 70 71 pspec := spec.Process 72 pspec.Args = []string{"true"} 73 74 for { 75 select { 76 case <-tctx.Done(): 77 if err := task.Kill(ctx, syscall.SIGKILL); err != nil { 78 logrus.WithError(err).Error("kill exec container's task") 79 } 80 <-statusC 81 return 82 default: 83 } 84 85 w.count++ 86 id := w.getID() 87 logrus.Debugf("starting exec %s", id) 88 start := time.Now() 89 90 if err := w.runExec(ctx, task, id, pspec); err != nil { 91 if err != context.DeadlineExceeded || 92 !strings.Contains(err.Error(), context.DeadlineExceeded.Error()) { 93 w.failures++ 94 logrus.WithError(err).Errorf("running exec %s", id) 95 errCounter.WithValues(err.Error()).Inc() 96 } 97 continue 98 } 99 // only log times are success so we don't scew the results from failures that go really fast 100 execTimer.WithValues(w.commit).UpdateSince(start) 101 } 102 } 103 104 func (w *execWorker) runExec(ctx context.Context, task containerd.Task, id string, spec *specs.Process) (err error) { 105 process, err := task.Exec(ctx, id, spec, cio.NullIO) 106 if err != nil { 107 return err 108 } 109 defer func() { 110 if _, derr := process.Delete(ctx, containerd.WithProcessKill); err == nil { 111 err = derr 112 } 113 }() 114 statusC, err := process.Wait(ctx) 115 if err != nil { 116 return err 117 } 118 if err := process.Start(ctx); err != nil { 119 return err 120 } 121 status := <-statusC 122 _, _, err = status.Result() 123 if err != nil { 124 if err == context.DeadlineExceeded || err == context.Canceled { 125 return nil 126 } 127 w.failures++ 128 errCounter.WithValues(err.Error()).Inc() 129 } 130 return nil 131 }