Browse code

Fix containerd task deletion after failed start

Deleting a containerd task whose status is Created fails with a
"precondition failed" error. This is because (aside from Windows)
a process is spawned when the task is created, and deleting the task
while the process is running would leak the process if it was allowed.
libcontainerd and the containerd plugin executor mistakenly try to clean
up from a failed start by deleting the created task, which will always
fail with the aforementined error. Change them to pass the
`WithProcessKill` delete option so the cleanup has a chance to succeed.

Signed-off-by: Cory Snider <csnider@mirantis.com>

Cory Snider authored on 2022/11/03 02:48:13
Showing 2 changed files
... ...
@@ -233,7 +233,9 @@ func (c *container) Start(ctx context.Context, checkpointDir string, withStdin b
233 233
 	stdinCloseSync <- t
234 234
 
235 235
 	if err := t.Start(ctx); err != nil {
236
-		if _, err := t.Delete(ctx); err != nil {
236
+		// Only Stopped tasks can be deleted. Created tasks have to be
237
+		// killed first, to transition them to Stopped.
238
+		if _, err := t.Delete(ctx, containerd.WithProcessKill); err != nil {
237 239
 			c.client.logger.WithError(err).WithField("container", c.c8dCtr.ID()).
238 240
 				Error("failed to delete task after fail start")
239 241
 		}
... ...
@@ -60,7 +60,7 @@ type c8dPlugin struct {
60 60
 // deleteTaskAndContainer deletes plugin task and then plugin container from containerd
61 61
 func (p c8dPlugin) deleteTaskAndContainer(ctx context.Context) {
62 62
 	if p.tsk != nil {
63
-		if _, err := p.tsk.Delete(ctx); err != nil && !errdefs.IsNotFound(err) {
63
+		if err := p.tsk.ForceDelete(ctx); err != nil && !errdefs.IsNotFound(err) {
64 64
 			p.log.WithError(err).Error("failed to delete plugin task from containerd")
65 65
 		}
66 66
 	}