@@ -19,19 +19,23 @@ package v2
19
19
import (
20
20
"context"
21
21
"errors"
22
+ "fmt"
22
23
"os"
23
24
"path/filepath"
24
25
26
+ "github.com/containerd/errdefs"
27
+ "github.com/containerd/log"
28
+
25
29
"github.com/containerd/containerd/v2/core/mount"
26
30
"github.com/containerd/containerd/v2/internal/cleanup"
27
31
"github.com/containerd/containerd/v2/pkg/namespaces"
28
32
"github.com/containerd/containerd/v2/pkg/timeout"
29
- "github.com/containerd/errdefs"
30
- "github.com/containerd/log"
31
33
)
32
34
33
- func (m * ShimManager ) loadExistingTasks (ctx context.Context ) error {
34
- nsDirs , err := os .ReadDir (m .state )
35
+ // LoadExistingShims loads existing shims from the path specified by stateDir
36
+ // rootDir is for cleaning up the unused paths of removed shims.
37
+ func (m * ShimManager ) LoadExistingShims (ctx context.Context , stateDir string , rootDir string ) error {
38
+ nsDirs , err := os .ReadDir (stateDir )
35
39
if err != nil {
36
40
return err
37
41
}
@@ -45,26 +49,26 @@ func (m *ShimManager) loadExistingTasks(ctx context.Context) error {
45
49
continue
46
50
}
47
51
log .G (ctx ).WithField ("namespace" , ns ).Debug ("loading tasks in namespace" )
48
- if err := m .loadShims (namespaces .WithNamespace (ctx , ns )); err != nil {
52
+ if err := m .loadShims (namespaces .WithNamespace (ctx , ns ), stateDir ); err != nil {
49
53
log .G (ctx ).WithField ("namespace" , ns ).WithError (err ).Error ("loading tasks in namespace" )
50
54
continue
51
55
}
52
- if err := m .cleanupWorkDirs (namespaces .WithNamespace (ctx , ns )); err != nil {
56
+ if err := m .cleanupWorkDirs (namespaces .WithNamespace (ctx , ns ), rootDir ); err != nil {
53
57
log .G (ctx ).WithField ("namespace" , ns ).WithError (err ).Error ("cleanup working directory in namespace" )
54
58
continue
55
59
}
56
60
}
57
61
return nil
58
62
}
59
63
60
- func (m * ShimManager ) loadShims (ctx context.Context ) error {
64
+ func (m * ShimManager ) loadShims (ctx context.Context , stateDir string ) error {
61
65
ns , err := namespaces .NamespaceRequired (ctx )
62
66
if err != nil {
63
67
return err
64
68
}
65
69
ctx = log .WithLogger (ctx , log .G (ctx ).WithField ("namespace" , ns ))
66
70
67
- shimDirs , err := os .ReadDir (filepath .Join (m . state , ns ))
71
+ shimDirs , err := os .ReadDir (filepath .Join (stateDir , ns ))
68
72
if err != nil {
69
73
return err
70
74
}
@@ -77,7 +81,7 @@ func (m *ShimManager) loadShims(ctx context.Context) error {
77
81
if len (id ) > 0 && id [0 ] == '.' {
78
82
continue
79
83
}
80
- bundle , err := LoadBundle (ctx , m . state , id )
84
+ bundle , err := LoadBundle (ctx , stateDir , id )
81
85
if err != nil {
82
86
// fine to return error here, it is a programmer error if the context
83
87
// does not have a namespace
@@ -102,78 +106,87 @@ func (m *ShimManager) loadShims(ctx context.Context) error {
102
106
bundle .Delete ()
103
107
continue
104
108
}
109
+ if err := m .loadShim (ctx , bundle ); err != nil {
110
+ log .G (ctx ).WithError (err ).Errorf ("failed to load shim %s" , bundle .Path )
111
+ bundle .Delete ()
112
+ continue
113
+ }
105
114
106
- var (
107
- runtime string
108
- )
115
+ }
116
+ return nil
117
+ }
109
118
110
- // If we're on 1.6+ and specified custom path to the runtime binary, path will be saved in 'shim-binary-path' file.
111
- if data , err := os .ReadFile (filepath .Join (bundle .Path , "shim-binary-path" )); err == nil {
112
- runtime = string (data )
113
- } else if err != nil && ! os .IsNotExist (err ) {
114
- log .G (ctx ).WithError (err ).Error ("failed to read `runtime` path from bundle" )
115
- }
119
+ func (m * ShimManager ) loadShim (ctx context.Context , bundle * Bundle ) error {
120
+ var (
121
+ runtime string
122
+ id = bundle .ID
123
+ )
124
+
125
+ // If we're on 1.6+ and specified custom path to the runtime binary, path will be saved in 'shim-binary-path' file.
126
+ if data , err := os .ReadFile (filepath .Join (bundle .Path , "shim-binary-path" )); err == nil {
127
+ runtime = string (data )
128
+ } else if err != nil && ! os .IsNotExist (err ) {
129
+ log .G (ctx ).WithError (err ).Error ("failed to read `runtime` path from bundle" )
130
+ }
116
131
117
- // Query runtime name from metadata store
118
- if runtime == "" {
119
- container , err := m .containers .Get (ctx , id )
120
- if err != nil {
121
- log .G (ctx ).WithError (err ).Errorf ("loading container %s" , id )
122
- if err := mount .UnmountRecursive (filepath .Join (bundle .Path , "rootfs" ), 0 ); err != nil {
123
- log .G (ctx ).WithError (err ).Errorf ("failed to unmount of rootfs %s" , id )
124
- }
125
- bundle .Delete ()
126
- continue
132
+ // Query runtime name from metadata store
133
+ if runtime == "" {
134
+ container , err := m .containers .Get (ctx , id )
135
+ if err != nil {
136
+ log .G (ctx ).WithError (err ).Errorf ("loading container %s" , id )
137
+ if err := mount .UnmountRecursive (filepath .Join (bundle .Path , "rootfs" ), 0 ); err != nil {
138
+ log .G (ctx ).WithError (err ).Errorf ("failed to unmount of rootfs %s" , id )
127
139
}
128
- runtime = container . Runtime . Name
140
+ return err
129
141
}
142
+ runtime = container .Runtime .Name
143
+ }
130
144
131
- runtime , err = m .resolveRuntimePath (runtime )
132
- if err != nil {
133
- bundle .Delete ()
134
- log . G ( ctx ). WithError ( err ). Error ( "failed to resolve runtime path" )
135
- continue
136
- }
145
+ runtime , err : = m .resolveRuntimePath (runtime )
146
+ if err != nil {
147
+ bundle .Delete ()
148
+
149
+ return fmt . Errorf ( "failed to resolve runtime path: %w" , err )
150
+ }
137
151
138
- binaryCall := shimBinary (bundle ,
139
- shimBinaryConfig {
140
- runtime : runtime ,
141
- address : m .containerdAddress ,
142
- ttrpcAddress : m .containerdTTRPCAddress ,
143
- schedCore : m .schedCore ,
144
- })
145
- shim , err := loadShimTask (ctx , bundle , func () {
146
- log .G (ctx ).WithField ("id" , id ).Info ("shim disconnected" )
147
-
148
- cleanupAfterDeadShim (cleanup .Background (ctx ), id , m .shims , m .events , binaryCall )
149
- // Remove self from the runtime task list.
150
- m .shims .Delete (ctx , id )
152
+ binaryCall := shimBinary (bundle ,
153
+ shimBinaryConfig {
154
+ runtime : runtime ,
155
+ address : m .containerdAddress ,
156
+ ttrpcAddress : m .containerdTTRPCAddress ,
157
+ schedCore : m .schedCore ,
151
158
})
152
- if err != nil {
153
- log .G (ctx ).WithError (err ).Errorf ("unable to load shim %q" , id )
154
- cleanupAfterDeadShim (ctx , id , m .shims , m .events , binaryCall )
155
- continue
156
- }
159
+ // TODO: It seems we can only call loadShim here if it is a sandbox shim?
160
+ shim , err := loadShimTask (ctx , bundle , func () {
161
+ log .G (ctx ).WithField ("id" , id ).Info ("shim disconnected" )
162
+
163
+ cleanupAfterDeadShim (cleanup .Background (ctx ), id , m .shims , m .events , binaryCall )
164
+ // Remove self from the runtime task list.
165
+ m .shims .Delete (ctx , id )
166
+ })
167
+ if err != nil {
168
+ cleanupAfterDeadShim (ctx , id , m .shims , m .events , binaryCall )
169
+ return fmt .Errorf ("unable to load shim %q: %w" , id , err )
170
+ }
157
171
158
- // There are 3 possibilities for the loaded shim here:
159
- // 1. It could be a shim that is running a task.
160
- // 2. It could be a sandbox shim.
161
- // 3. Or it could be a shim that was created for running a task but
162
- // something happened (probably a containerd crash) and the task was never
163
- // created. This shim process should be cleaned up here. Look at
164
- // containerd/containerd#6860 for further details.
165
-
166
- _ , sgetErr := m .sandboxStore .Get (ctx , id )
167
- pInfo , pidErr := shim .Pids (ctx )
168
- if sgetErr != nil && errors .Is (sgetErr , errdefs .ErrNotFound ) && (len (pInfo ) == 0 || errors .Is (pidErr , errdefs .ErrNotFound )) {
169
- log .G (ctx ).WithField ("id" , id ).Info ("cleaning leaked shim process" )
170
- // We are unable to get Pids from the shim and it's not a sandbox
171
- // shim. We should clean it up her.
172
- // No need to do anything for removeTask since we never added this shim.
173
- shim .delete (ctx , false , func (ctx context.Context , id string ) {})
174
- } else {
175
- m .shims .Add (ctx , shim .ShimInstance )
176
- }
172
+ // There are 3 possibilities for the loaded shim here:
173
+ // 1. It could be a shim that is running a task.
174
+ // 2. It could be a sandbox shim.
175
+ // 3. Or it could be a shim that was created for running a task but
176
+ // something happened (probably a containerd crash) and the task was never
177
+ // created. This shim process should be cleaned up here. Look at
178
+ // containerd/containerd#6860 for further details.
179
+
180
+ _ , sgetErr := m .sandboxStore .Get (ctx , id )
181
+ pInfo , pidErr := shim .Pids (ctx )
182
+ if sgetErr != nil && errors .Is (sgetErr , errdefs .ErrNotFound ) && (len (pInfo ) == 0 || errors .Is (pidErr , errdefs .ErrNotFound )) {
183
+ log .G (ctx ).WithField ("id" , id ).Info ("cleaning leaked shim process" )
184
+ // We are unable to get Pids from the shim and it's not a sandbox
185
+ // shim. We should clean it up her.
186
+ // No need to do anything for removeTask since we never added this shim.
187
+ shim .delete (ctx , false , func (ctx context.Context , id string ) {})
188
+ } else {
189
+ m .shims .Add (ctx , shim .ShimInstance )
177
190
}
178
191
return nil
179
192
}
@@ -198,13 +211,13 @@ func loadShimTask(ctx context.Context, bundle *Bundle, onClose func()) (_ *shimT
198
211
return s , nil
199
212
}
200
213
201
- func (m * ShimManager ) cleanupWorkDirs (ctx context.Context ) error {
214
+ func (m * ShimManager ) cleanupWorkDirs (ctx context.Context , rootDir string ) error {
202
215
ns , err := namespaces .NamespaceRequired (ctx )
203
216
if err != nil {
204
217
return err
205
218
}
206
219
207
- f , err := os .Open (filepath .Join (m . root , ns ))
220
+ f , err := os .Open (filepath .Join (rootDir , ns ))
208
221
if err != nil {
209
222
return err
210
223
}
@@ -220,7 +233,7 @@ func (m *ShimManager) cleanupWorkDirs(ctx context.Context) error {
220
233
// this can happen on a reboot where /run for the bundle state is cleaned up
221
234
// but that persistent working dir is left
222
235
if _ , err := m .shims .Get (ctx , dir ); err != nil {
223
- path := filepath .Join (m . root , ns , dir )
236
+ path := filepath .Join (rootDir , ns , dir )
224
237
if err := os .RemoveAll (path ); err != nil {
225
238
log .G (ctx ).WithError (err ).Errorf ("cleanup working dir %s" , path )
226
239
}
0 commit comments