drainExecSyncIO drains process IO with timeout after exec init process exits. By default, the child processes spawned by exec process will inherit standard io file descriptors. The shim server creates a pipe as data channel. Both exec process and its children write data into the write end of the pi
(ctx context.Context, execProcess containerd.Process, drainExecIOTimeout time.Duration, attachDone <-chan struct{})
| 300 | // the write end of the pipe for a year! It doesn't make senses that CRI plugin |
| 301 | // should wait for it. |
| 302 | func drainExecSyncIO(ctx context.Context, execProcess containerd.Process, drainExecIOTimeout time.Duration, attachDone <-chan struct{}) error { |
| 303 | var timerCh <-chan time.Time |
| 304 | |
| 305 | if drainExecIOTimeout != 0 { |
| 306 | timer := time.NewTimer(drainExecIOTimeout) |
| 307 | defer timer.Stop() |
| 308 | |
| 309 | timerCh = timer.C |
| 310 | } |
| 311 | |
| 312 | select { |
| 313 | case <-timerCh: |
| 314 | case <-attachDone: |
| 315 | log.G(ctx).Tracef("Stream pipe for exec process %q done", execProcess.ID()) |
| 316 | return nil |
| 317 | } |
| 318 | |
| 319 | log.G(ctx).Debugf("Exec process %q exits but the io is still held by other processes. Trying to delete exec process to release io", execProcess.ID()) |
| 320 | _, err := execProcess.Delete(ctx, containerd.WithProcessKill) |
| 321 | if err != nil { |
| 322 | if !errdefs.IsNotFound(err) { |
| 323 | return fmt.Errorf("failed to release exec io by deleting exec process %q: %w", |
| 324 | execProcess.ID(), err) |
| 325 | } |
| 326 | } |
| 327 | return fmt.Errorf("failed to drain exec process %q io in %s because io is still held by other processes", |
| 328 | execProcess.ID(), drainExecIOTimeout) |
| 329 | } |
searching dependent graphs…