Go의 프로세스 시간 초과 및 하위 프로세스 종료
Go에서 하위 프로세스를 시간 초과하고 종료하는 기능은 시스템 안정성을 유지하고 애플리케이션 응답성을 보장합니다. 그러나 다음 코드에서 설명한 것처럼 프로세스 종료 시 불일치가 발생할 수 있습니다.
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") }()
이 코드에서는 시간 초과 메커니즘에 결함이 있는 것으로 보입니다. "It's dead Jim"은 올바르게 인쇄되지만 실패합니다. "Done waiting"을 인쇄하고 하위 프로세스를 실행 상태로 둡니다.
근본 원인: SIGKILL 제한사항
프로세스를 종료하기 위해 cmd.Process.Signal(syscall.SIGKILL)을 사용하는 것이 원인입니다. 어떤 경우에는 SIGKILL이 하위 프로세스를 종료하기에 충분하지 않을 수 있습니다. 근본적인 이유는 최신 운영 체제가 각 프로세스에 대해 별도의 프로세스 그룹을 유지하기 때문입니다. 그룹의 한 프로세스가 SIGKILL을 사용하여 다른 그룹의 다른 프로세스를 종료하려고 시도하면 신호가 효과적으로 전달되지 않을 수 있습니다.
해결책: 부정적인 프로세스 그룹 ID 사용
이 문제를 회피하기 위한 솔루션에는 syscall.Kill과 함께 부정적인 프로세스 그룹 ID(-pgid)를 사용하는 것이 포함됩니다. 프로세스 그룹 ID 앞에 빼기 기호를 추가하면 신호가 개별 프로세스가 아닌 전체 프로세스 그룹으로 전송됩니다. 이렇게 하면 하위 프로세스도 종료됩니다.
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()
주의 사항 및 플랫폼 고려 사항
이 솔루션은 모든 운영 체제에서 이식 가능하지 않을 수 있다는 점에 유의하는 것이 중요합니다. . 프로세스 그룹을 조작하는 기능은 플랫폼마다 다릅니다. 이 솔루션은 테스트를 거쳐 macOS Yosemite에서 작동하지만 Windows 또는 일부 Linux 버전과 같은 다른 플랫폼에서는 동작이 다를 수 있습니다.
위 내용은 잠재적인 OS 불일치를 고려하여 Go에서 하위 프로세스를 안정적으로 시간 초과하고 종료하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!