Délai d'expiration du processus et terminaison du processus enfant dans Go
Dans Go, la possibilité d'expirer le délai d'attente et de mettre fin aux processus enfants est cruciale pour maintenir la stabilité du système et assurer la réactivité des applications. Cependant, des incohérences dans la fin du processus peuvent survenir, comme le démontre le code suivant :
func() { var output bytes.Buffer cmd := exec.Command("Command", args...) cmd.Dir = filepath.Dir(srcFile) cmd.Stdout, cmd.Stderr = &output, &output if err := cmd.Start(); err != nil { return err } defer time.AfterFunc(time.Second*2, func() { fmt.Printf("Nobody got time fo that\n") if err := cmd.Process.Signal(syscall.SIGKILL); err != nil { fmt.Printf("Error:%s\n", err) } fmt.Printf("It's dead Jim\n") }).Stop() err := cmd.Wait() fmt.Printf("Done waiting\n") }()
Dans ce code, le mécanisme de délai d'attente semble être défectueux : alors qu'il affiche correctement "C'est mort Jim", il ne parvient pas à imprime « Fin d'attente » et laisse le processus enfant en cours d'exécution.
Cause fondamentale : SIGKILL Limitations
Le coupable réside dans l'utilisation de cmd.Process.Signal(syscall.SIGKILL) pour terminer le processus. Dans certains cas, SIGKILL peut ne pas suffire à tuer les processus enfants. La raison sous-jacente est que les systèmes d’exploitation modernes maintiennent des groupes de processus distincts pour chaque processus. Lorsqu'un processus d'un groupe tente de terminer un autre processus d'un groupe différent à l'aide de SIGKILL, le signal peut ne pas être délivré efficacement.
Solution : utilisation d'un ID de groupe de processus négatif
Pour contourner ce problème, la solution consiste à utiliser un ID de groupe de processus négatif (-pgid) en conjonction avec syscall.Kill. En préfixant l'ID du groupe de processus avec un signe moins, le signal est envoyé à l'ensemble du groupe de processus plutôt qu'à un processus individuel. Cela garantit que les processus enfants sont également terminés :
cmd := exec.Command( some_command ) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} cmd.Start() pgid, err := syscall.Getpgid(cmd.Process.Pid) if err == nil { syscall.Kill(-pgid, 15) // note the minus sign } cmd.Wait()
Précautions et considérations relatives à la plate-forme
Il est important de noter que cette solution peut ne pas être portable sur tous les systèmes d'exploitation. . La capacité de manipuler des groupes de processus varie selon les différentes plates-formes. Bien que cette solution ait été testée et fonctionne sur macOS Yosemite, son comportement peut différer sur d'autres plateformes telles que Windows ou certaines versions de Linux.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!