2 votes

Le processus ne meurt pas après l'appel à cmd.Process.Kill()

J'ai un programme qui suit les changements de fichiers et doit redémarrer un processus spécifié lors d'un changement de fichier.

J'utilise cmd.Process.Kill() pour tuer le processus précédent mais il reste en vie après Kill() appelé.

Un morceau de code lié au processus de démarrage du projet :

// 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() commence son travail et Cancel() annulez-le. Les deux sont appelés dans des goroutines séparées.

Le code source complet est aquí

2voto

Denis Sedchenko Points 64

Le problème était que le processus principal sh a été tué mais le processus enfant sleep était encore en vie.

La solution était d'assigner un groupe de processus au processus principal et de tuer un groupe de processus entier.

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

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

La solution a été trouvée aquí

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X