@@ -22,11 +22,16 @@ package main
22
22
import (
23
23
"context"
24
24
"os"
25
+ "syscall"
25
26
26
27
"github.com/containerd/containerd/errdefs"
28
+ "github.com/containerd/containerd/namespaces"
27
29
"github.com/containerd/containerd/runtime/v2/shim"
28
30
taskAPI "github.com/containerd/containerd/runtime/v2/task"
29
31
ptypes "github.com/gogo/protobuf/types"
32
+
33
+ "github.com/pkg/errors"
34
+ exec "golang.org/x/sys/execabs"
30
35
)
31
36
32
37
var (
@@ -43,8 +48,63 @@ type service struct {
43
48
}
44
49
45
50
// StartShim is a binary call that executes a new shim returning the address
46
- func (s * service ) StartShim (ctx context.Context , opts shim.StartOpts ) (string , error ) {
47
- return "" , nil
51
+ func (s * service ) StartShim (ctx context.Context , opts shim.StartOpts ) (_ string , retErr error ) {
52
+ cmd , err := newCommand (ctx , opts .ID , opts .ContainerdBinary , opts .Address , opts .TTRPCAddress )
53
+ if err != nil {
54
+ return "" , err
55
+ }
56
+ address , err := shim .SocketAddress (ctx , opts .Address , opts .ID )
57
+ if err != nil {
58
+ return "" , err
59
+ }
60
+ socket , err := shim .NewSocket (address )
61
+ if err != nil {
62
+ if ! shim .SocketEaddrinuse (err ) {
63
+ return "" , err
64
+ }
65
+ if err := shim .RemoveSocket (address ); err != nil {
66
+ return "" , errors .Wrap (err , "remove already used socket" )
67
+ }
68
+ if socket , err = shim .NewSocket (address ); err != nil {
69
+ return "" , err
70
+ }
71
+ }
72
+ defer func () {
73
+ if retErr != nil {
74
+ socket .Close ()
75
+ _ = shim .RemoveSocket (address )
76
+ }
77
+ }()
78
+ // make sure that reexec shim-v2 binary use the value if need
79
+ if err := shim .WriteAddress ("address" , address ); err != nil {
80
+ return "" , err
81
+ }
82
+
83
+ f , err := socket .File ()
84
+ if err != nil {
85
+ return "" , err
86
+ }
87
+
88
+ cmd .ExtraFiles = append (cmd .ExtraFiles , f )
89
+
90
+ if err := cmd .Start (); err != nil {
91
+ f .Close ()
92
+ return "" , err
93
+ }
94
+ defer func () {
95
+ if retErr != nil {
96
+ cmd .Process .Kill ()
97
+ }
98
+ }()
99
+ // make sure to wait after start
100
+ go cmd .Wait ()
101
+ if err := shim .WritePidFile ("shim.pid" , cmd .Process .Pid ); err != nil {
102
+ return "" , err
103
+ }
104
+ if err := shim .AdjustOOMScore (cmd .Process .Pid ); err != nil {
105
+ return "" , errors .Wrap (err , "failed to adjust OOM score for shim" )
106
+ }
107
+ return address , nil
48
108
}
49
109
50
110
// Cleanup is a binary call that cleans up any resources used by the shim when the service crashes
@@ -137,3 +197,30 @@ func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*pt
137
197
func (s * service ) Wait (ctx context.Context , r * taskAPI.WaitRequest ) (* taskAPI.WaitResponse , error ) {
138
198
return nil , errdefs .ErrNotImplemented
139
199
}
200
+
201
+ func newCommand (ctx context.Context , id , containerdBinary , containerdAddress , containerdTTRPCAddress string ) (* exec.Cmd , error ) {
202
+ ns , err := namespaces .NamespaceRequired (ctx )
203
+ if err != nil {
204
+ return nil , err
205
+ }
206
+ self , err := os .Executable ()
207
+ if err != nil {
208
+ return nil , err
209
+ }
210
+ cwd , err := os .Getwd ()
211
+ if err != nil {
212
+ return nil , err
213
+ }
214
+ args := []string {
215
+ "-namespace" , ns ,
216
+ "-id" , id ,
217
+ "-address" , containerdAddress ,
218
+ }
219
+ cmd := exec .Command (self , args ... )
220
+ cmd .Dir = cwd
221
+ cmd .Env = append (os .Environ (), "GOMAXPROCS=4" )
222
+ cmd .SysProcAttr = & syscall.SysProcAttr {
223
+ Setpgid : true ,
224
+ }
225
+ return cmd , nil
226
+ }
0 commit comments