func handleSignals()

in internal/platform/utils/cmd.go [200:242]


func handleSignals(cmd *exec.Cmd, waitCh <-chan error, timeout time.Duration, timeoutExitCode int) (int, error) {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
	defer func() {
		signal.Stop(sigChan) // Use Stop to prevent panics
		close(sigChan)
	}()

	var timeoutCh = time.After(timeout)

	for {
		select {
		case <-sigChan:
			if err := RequestTermination(cmd.Process); err != nil && !errors.Is(
				err,
				os.ErrProcessDone,
			) { // Use errors.Is for semantic comparison
				log.Error("Error terminating process: ", err)
			}
		case <-timeoutCh:
			if err := RequestTermination(cmd.Process); err != nil {
				log.Fatal("failed to kill process on timeout: ", err)
			}
			_, _ = cmd.Process.Wait()
			return timeoutExitCode, nil
		case ret := <-waitCh:
			var exitError *exec.ExitError
			if errors.As(ret, &exitError) {
				log.Println(ret)
				waitStatus := exitError.Sys().(syscall.WaitStatus)
				if waitStatus.Exited() {
					return waitStatus.ExitStatus(), nil
				}
				log.Println("Process killed (OOM?)")
				return QodanaOutOfMemoryExitCode, nil
			}
			if ret != nil {
				log.Println(ret)
			}
			return cmd.ProcessState.ExitCode(), ret
		}
	}
}