2016-09-04 4 views
1

이 코드는 deadlock condition에 대해 읽었습니다.이 코드는 내 코드 (아래)에 영향을줍니다. 이 코드는 지난 12 년 동안 Windows Server 2003 (.net 2.0)에서 완벽하게 작동했습니다. 이제는 항상 교착 상태가있는 Windows Server 2012로이 서버를 이동하려고했습니다.프로세스 제거 .WaitForExit()/StandardOutput 교착 상태

내 DLL은 "anyCPU"(여전히 .net 2.0을 대상으로 함)로 빌드되지만 실행되는 실행 프로세스는 절대적으로 32 비트이며 Server 2003에서 Server 2012 로의 이동은 32 비트에서 64 비트로 이동합니다. bit OS.

문제를 해결하기 위해해야 ​​할 일이 무엇인지 이해하고 있지만이 동작이 Server 2003에서 Server 2012로 변경된 이유를 알고있는 사람이 있습니까?

public string DoMyProcess(string filenameAndPath, string arguments) 
{ 
    string stdout=""; 
    int exitCode = 0;    

    try 
    {    
     ProcessStartInfo procStartInfo = new ProcessStartInfo(); 
     procStartInfo.FileName = filenameAndPath; 
     procStartInfo.CreateNoWindow = true; 
     procStartInfo.Arguments = arguments;    
     procStartInfo.RedirectStandardOutput = true; 
     procStartInfo.UseShellExecute = false; 

     System.Diagnostics.Process theProcess = null; 
     try 
     { 
      theProcess = Process.Start(procStartInfo); 
      theProcess.WaitForExit(); 

      exitCode = theProcess.ExitCode; 

      // moving this ABOVE WaitForExit should eliminate deadlocks 
      // But why did it always work on Server 2003 but not on Server 2012? 
      stdout = theProcess.StandardOutput.ReadToEnd(); 

     } 
     catch (System.Exception e) 
     { 
      string errMsg = e.Message; 
      log_the_error("threw an exception: " + e.Message); 
     }     
    }   

    return stdout; 
} 

UPDATE :

 try 
     { 
      theProcess = Process.Start(procStartInfo); 
      stdout = theProcess.StandardOutput.ReadToEnd();      
     } 
     catch (System.Exception e) 
     { 
      string errMsg = e.Message; 
      log_the_error("threw an exception: " + e.Message); 
     }     
    }   

어떤 다른 조건이 교착 상태가 발생할 수 있습니다 : 아직 심지어 권장하는 위의 코드를 변경 한 후, 존재

미스터리 교착? 만약 내가 StandardError를 검사한다면, 유용한 것을 알려줄 수 있을까요?

업데이트 # 2 :

FWIW, 우리는 프로비저닝 만 가끔이 코드는 12 년에 실행 된 원래의 시스템 구성했다 IIS 6 (실행하는 다른 Windows Server 2003 (32 비트) 이중 자물쇠). 서버 2012에서 교착 상태가되는 동일한 코드는이 서버 2003에서 취소되지 않습니다.

이제 우리는이 문제를 재현하는 최소한의 완전한 코드를 갖게되었습니다. 그러나 우리가 라이센스 한 .exe에는 프로세스가 실행 중이므로 게시를 막는 기밀 조항이 있습니다. 전문가가 여기에 도움이되지 않는다는 것을 알고 있습니다.

우리가 만난 한가지 힌트는 실제 서버에 설치된 Visual Studio 2013 디버거를 통해 실행될 때 프로세스가 교착 상태가 발생하거나 멈추지 않고 서버 외부의 브라우저에서 프로세스를 호출하는 것입니다. 이상하게도 - 2012 년 서버의 브라우저에서 해당 테스트 페이지에 연결할 수 없습니다. 브라우저는 "연결"하고 결국 타임 아웃합니다 (그러나 동일한 서버에서 호스팅되는 다른 사이트/동일한 IIS 8에 도달 할 수 있음).)

관리 명령 셸 또는 관리자가 아닌 명령 셸에서 수동으로 실행하는 명령 줄 매개 변수가 완벽하게 작동하기 때문에이 명령 줄에서 64 비트/WOW64 문제라고 생각하기 어렵습니다 32 비트 실행 파일이거나 필수 DLL입니다. 우리는 권한이 문제를 일으킬 수있는 장소를 계속 검색합니다 (프로세스는 temp 폴더에 작성해야합니다. 임시 폴더는 지금은 c : \ temp에 배치했습니다).

+1

잘못된 코드 패턴이 인터넷에 널리 퍼져 있지만, [Process.OutputDataReceived Event] (https://msdn.microsoft.com/en-us/library/system.diagnostics)에서 제공하는 MS 예제를 사용해보십시오. .process.outputdatareceived (v = vs.110) .aspx? cs-save-lang = 1 & cs-lang = csharp # code-snippet-2)를 시작점으로 사용합니다. 해당 이벤트와 다른 프로세스 이벤트가 보조 스레드에 도착 했으므로 적절하게 계획을 세우십시오. – TnTinMn

+0

re : 편집 한 업데이트, 교착 상태를 유발할 수있는 코드가 코드에 남아 있지 않습니다. 그렇다고해서 ... [mcve]를 제공하지 않았기 때문에 여기서 다른 코드가 무엇인지 알 수는 없습니다. 'StandardError'를 읽는 것은 유용 할 수도 있고 그렇지 않을 수도 있습니다; 교착 상태로 외부 프로세스에서 어떤 종류의 오류 또는 사용자 프롬프트를 잘못 해석 할 수 있습니다. 실제로는 사용자 또는 다른 사람이 응답하기를 기다리고있을 때입니다. 'StandardError'를 _do_ 리다이렉트하면, 데드락의 가능성을 소개하고이를 피하는 지 확인하고 싶을 것이다. –

+1

나는 여기에있는 질문과 다른 질문에 대답하면서 코드를 교착 상태없이 'StandardOutput'과'StandardError' 둘 모두를 리디렉션하는 예제를 포함하는 몇 가지 다른 대답을 갖고 있습니다. 그 중 하나 이상이 유용 할 수 있습니다. http://stackoverflow.com/a/33508142, http://stackoverflow.com/a/26722542 및 http://stackoverflow.com/a/38881345 –

답변

1

좋은 Minimal, Complete, and Verifiable code example 없이는 완전히 대답 할 수 없습니다.

내가 말할 수있는 것은 코드가 항상 손상되었으며 항상 교착 상태가 발생할 가능성이 있다는 것입니다. 프로세스가 종료 될 때까지 프로세스에서 아무 것도 읽지 못하지만 버퍼가 프로세스를 채우고 차단한다는 사실을 stdout에 많은 양으로 기록하면 프로세스를 종료 할 수 없습니다.

아무 것도 다시 컴파일하지 않았지만 이전에 교착 상태가 발생했을 때 교착 상태가 발생했다면 가장 많이 발생하는 설명은 시작한 프로세스가 이전보다 stdout에 더 많은 것을 씁니다. 나는. 모든 출력은 이전에 버퍼에 맞게 사용되었지만 지금은 그렇지 않습니다. (나는 새로운 OS에서 버퍼 크기가 줄어들 가능성도 있다고 생각하지만, 그렇게 느껴지지는 않는다.)

전화를 걸어 ReadToEnd()으로 이동해야합니다. 실제로 WaitForExit()을 삭제해야합니다. ReadToEnd()으로 전화하면 프로세스가 실제로 종료 될 때까지 완료되지 않으므로 나중에 WaitForExit()을 호출하면 무의미합니다.

+0

나는 당신이 옳다고 믿습니다. 이 코드는 충분히 경험이 풍부한 공급 업체의 사례 중 일부였습니다. 당시 엔지니어는 .net과 함께 newb였습니다. – SMGreenfield