Skip to content

Commit df3a94f

Browse files
committed
Ensure we can always terminate the parent process on error
As we all know, we should terminate the parent process if there is an error when starting the container process, but these terminate function are called in many places, for example: `initProcess`, `setnsProcess`, and `Container`, if we forget this terminate call for some errors, it will let the container in unknown state, so we should change to call it in some final places. Signed-off-by: lifubang <[email protected]>
1 parent 3778ae6 commit df3a94f

File tree

3 files changed

+40
-24
lines changed

3 files changed

+40
-24
lines changed

libcontainer/container_linux.go

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,28 @@ func (c *Container) Set(config configs.Config) error {
201201

202202
// Start starts a process inside the container. Returns error if process fails
203203
// to start. You can track process lifecycle with passed Process structure.
204-
func (c *Container) Start(process *Process) error {
204+
func (c *Container) Start(process *Process) (retErr error) {
205205
c.m.Lock()
206-
defer c.m.Unlock()
206+
defer func() {
207+
if retErr != nil {
208+
c.terminate(process)
209+
}
210+
c.m.Unlock()
211+
}()
207212
return c.start(process)
208213
}
209214

210215
// Run immediately starts the process inside the container. Returns an error if
211216
// the process fails to start. It does not block waiting for the exec fifo
212217
// after start returns but opens the fifo after start returns.
213-
func (c *Container) Run(process *Process) error {
218+
func (c *Container) Run(process *Process) (retErr error) {
214219
c.m.Lock()
215-
defer c.m.Unlock()
220+
defer func() {
221+
if retErr != nil {
222+
c.terminate(process)
223+
}
224+
c.m.Unlock()
225+
}()
216226
if err := c.start(process); err != nil {
217227
return err
218228
}
@@ -229,6 +239,30 @@ func (c *Container) Exec() error {
229239
return c.exec()
230240
}
231241

242+
// terminate is to kill the container's init/exec process when got failure.
243+
func (c *Container) terminate(process *Process) {
244+
if process.ops == nil {
245+
return
246+
}
247+
if process.Init {
248+
if err := ignoreTerminateErrors(process.ops.terminate()); err != nil {
249+
logrus.WithError(err).Warn("unable to terminate initProcess")
250+
}
251+
if err := c.cgroupManager.Destroy(); err != nil {
252+
logrus.WithError(err).Warn("unable to destroy cgroupManager")
253+
}
254+
if c.intelRdtManager != nil {
255+
if err := c.intelRdtManager.Destroy(); err != nil {
256+
logrus.WithError(err).Warn("unable to destroy intelRdtManager")
257+
}
258+
}
259+
return
260+
}
261+
if err := ignoreTerminateErrors(process.ops.terminate()); err != nil {
262+
logrus.WithError(err).Warn("unable to terminate setnsProcess")
263+
}
264+
}
265+
232266
func (c *Container) exec() error {
233267
path := filepath.Join(c.stateDir, execFifoFilename)
234268
pid := c.initProcess.pid()
@@ -359,12 +393,7 @@ func (c *Container) start(process *Process) (retErr error) {
359393
return err
360394
}
361395

362-
if err := c.config.Hooks.Run(configs.Poststart, s); err != nil {
363-
if err := ignoreTerminateErrors(parent.terminate()); err != nil {
364-
logrus.Warn(fmt.Errorf("error running poststart hook: %w", err))
365-
}
366-
return err
367-
}
396+
return c.config.Hooks.Run(configs.Poststart, s)
368397
}
369398
}
370399
return nil

libcontainer/process.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
var errInvalidProcess = errors.New("invalid process")
1313

1414
type processOperations interface {
15+
terminate() error
1516
wait() (*os.ProcessState, error)
1617
signal(sig os.Signal) error
1718
pid() int

libcontainer/process_linux.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,6 @@ func (p *setnsProcess) start() (retErr error) {
151151
if werr != nil {
152152
logrus.WithError(werr).Warn()
153153
}
154-
err := ignoreTerminateErrors(p.terminate())
155-
if err != nil {
156-
logrus.WithError(err).Warn("unable to terminate setnsProcess")
157-
}
158154
}
159155
}()
160156

@@ -563,16 +559,6 @@ func (p *initProcess) start() (retErr error) {
563559
if werr != nil {
564560
logrus.WithError(werr).Warn()
565561
}
566-
567-
// Terminate the process to ensure we can remove cgroups.
568-
if err := ignoreTerminateErrors(p.terminate()); err != nil {
569-
logrus.WithError(err).Warn("unable to terminate initProcess")
570-
}
571-
572-
_ = p.manager.Destroy()
573-
if p.intelRdtManager != nil {
574-
_ = p.intelRdtManager.Destroy()
575-
}
576562
}
577563
}()
578564

0 commit comments

Comments
 (0)