2017-04-16 1 views
1

나는 여기서 안전하게 goroutine을 종료 할 수 없다는 문제가 있습니다. I 호출있어 해당 프로세스를 시작해야 할 필요가있을 때마다외부 입출력으로 차단 된 goroutine을 중지하는 방법 프로세스가 시작 되었습니까?

exec.Command(args[0], args[1]...) // args[0] is a base command 

:

I는 (파이프 프로세스의 표준 출력 파이프 stdin을 (CMD) 저장) exec.Command 사용 만들어진 외부 프로세스 봉착 :

shutdown := make(chan struct{}) 
// Run the routine which will read from process and send the data to CmdIn channel 
go pr.cmdInRoutine() 
// Run the routine which will read from CmdOut and write to process 
go pr.cmdOutRoutine() 

cmdInRo : 다음

cmd.Start() 

는 시작과 부착에 나는 2 goroutines를 실행 해요 utine :

func (pr *ExternalProcess) cmdInRoutine() { 
    app.At(te, "cmdInRoutine") 

    for { 
     println("CMDINROUTINE") 
     select { 
     case <-pr.shutdown: 
      println("!!! Shutting cmdInRoutine down !!!") 
      return 
     default: 
      println("Inside the for loop of the CmdInRoutine") 
      if pr.stdOutPipe == nil { 
       println("!!! Standard output pipe is nil. Sending Exit Request !!!") 
       pr.ProcessExit <- true 
       close(pr.shutdown) 
       return 
      } 

      buf := make([]byte, 2048) 

      size, err := pr.stdOutPipe.Read(buf) 
      if err != nil { 
       println("!!! Sending exit request from cmdInRoutine !!!") 
       pr.ProcessExit <- true 
       close(pr.shutdown) 
       return 
      } 

      println("--- Received data for sending to CmdIn:", string(buf[:size])) 
      pr.CmdIn <- buf[:size] 
     } 

    } 
} 

cmdOutRoutine : 여기

func (pr *ExternalProcess) cmdOutRoutine() { 
    app.At(te, "cmdOutRoutine") 

    for { 
     select { 
     case <-pr.shutdown: 
      println("!!! Shutting cmdOutRoutine down !!!") 
      return 
     case data := <-pr.CmdOut: 
      println("Received data for sending to Process: ", data) 
      if pr.stdInPipe == nil { 
       println("!!! Standard input pipe is nil. Sending Exit Request !!!") 
       pr.ProcessExit <- true 
       return 
      } 

      println("--- Received input to write to external process:", string(data)) 
      _, err := pr.stdInPipe.Write(append(data, '\n')) 
      if err != nil { 
       println("!!! Couldn't Write To the std in pipe of the process !!!") 
       pr.ProcessExit <- true 
       return 
      } 
     } 
    } 
} 

흥미있는 경우 : - 사실 I가 통지 된 프로세스는 EOF를 보낼 때

1)합니다 (pr.ProcessExit < 상관 없어 부모 처리기는 채널을 사용하여 프로세스를 중지하고 종료합니다) cmdInRoutine 종료 채널도 닫고 있습니다. cmdOutRouti ne을 종료하려면 select 문 내부에 기본 값이 없으므로 exit 또는 데이터를 차단하고 대기중인 프로세스를 기록한 후 stdInPipe을 사용하여 데이터를 기록합니다.

2) goroutines를 그냥 멈추고 프로세스를 실행하고 싶을 때 (예 : 읽기를 일시 중지하고 쓰기) 종료 채널을 닫고 싶습니다. 두 개의 goroutines가 끝나기를 바랍니다.
- cmdOutRoutine 인쇄 !!! cmdOutRoutine 종료! 기본 케이스를 가지고 종료 채널을 폐쇄하는 것은 거의 즉시
복귀가 발생하지 않습니다를 선택하기 때문에 - cmdOutRoutine 아무것도 인쇄되지 않습니다 내가 그것도 반환하지 있다는 이상한 느낌을 보내고있어, 나는 그것은 차단 것 때문에 생각 stdInPipe에서 읽는 기본 사례입니다.

내가 for 루프 전에 cmdOutRoutine 안에 다른 goroutine을 실행하는 생각과 채널로 변환 프로세스의 STDIN 데이터가 그때 cmdInRoutine
에 기본 케이스를 제거 할 수있을 것이다 그러나 이것은 또 다른 생성

문제는 그 새로운 goroutine은 여전히 ​​실행중인 프로세스의stdIn에서 읽음으로 막힐 것입니다.

모든 아이디어를 어떻게 이것이 goroutines을 언제 종료와 시작의 요구 사항 (공정 I/O)이 아니라 실행중인 프로세스 자체를 충족하기 위해 (논리를 수정) 해결할 수 있습니까? 또는 읽지 못하고 쓰는 전화를 차단하는 방법이 있습니까? 아직 알지 못합니다.

고마워요.

+0

당신은 두 개의 별도의 루틴을 실행해야, 당신은 두 개의 별도의 종료 채널을 사용해야합니다. 당신처럼 하나만 가지고 있다면, 채널에서 차단 신호를 먼저 수집하고 다른 하나는 차단하도록하는 방법을 모를 수 있습니다. – RayfenWindspear

+0

또한 명령을 실행 한 후에 다시 사용할 수 없습니다. https://golang.org/pkg/os/exec/#Cmd – RayfenWindspear

+1

@RayfenWindspear 단일 종료 채널을 사용하는 것이 좋습니다. 닫힌 채널에서 읽으면 즉시 0 값이 반환되므로 두 goroutine이 종료 신호를 수집합니다. – user1431317

답변

관련 문제