Denis Sedchenko
Denis Sedchenko

Reputation: 188

Process doesn't die after cmd.Process.Kill() call

I've a program that tracks file change and should restart a specified process on file change.

I use cmd.Process.Kill() to kill previous process but it keeps alive after Kill() called.

Some piece of code related to process start from project:

// ShellPlugin allows to run shell commands in task runner 
type ShellPlugin struct {
    scope  *scope.Scope
    params Params
    log    logging.Logger
    done chan bool
}

// Call calls a plugin
func (p *ShellPlugin) Call(tx *job.RunContext, r plugins.JobRunner) (err error) {
    defer close(p.done)

    // process: /bin/sh -c ping google.com
    cmd, err := p.params.createProcess(p.scope)
    if err != nil {
        return fmt.Errorf("failed to create process to execute command '%s': %s", p.params.Command, err)
    }

    p.log.Debug("command: '%s'", p.params.Command)
    p.log.Debug(`starting process "%s"...`, strings.Join(cmd.Args, " "))

    if err = cmd.Start(); err != nil {
        return fmt.Errorf(`failed to execute command "%s": %s`, strings.Join(cmd.Args, " "), err)
    }

    go func() {
        select {
        case <- p.done:
            p.log.Debug("received stop signal")
            if err := cmd.Process.Kill(); err != nil {
                p.log.Warn("kill: %s", err.Error())
            }
            p.log.Debug("Killed")
        }
    }()

    if err := cmd.Wait(); err != nil {
        return formatExitError(err)
    }

    p.log.Debug("done")
    return nil
}

// Cancel called when task should be canceled
func (p *ShellPlugin) Cancel(ctx *job.RunContext) error {
    p.done <- true
    return nil
}

Call() starts job and Cancel() cancel it. Both called in separate goroutine.

Full source code is here

Upvotes: 2

Views: 259

Answers (1)

Denis Sedchenko
Denis Sedchenko

Reputation: 188

The issue was that the main process sh was killed but child process sleep was still alive.

The solution was to assign process group to the main process and kill a whole process group.

// assign process group
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}

// Kill pg
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)

Solution was found here

Upvotes: 2

Related Questions