source

왜 환경인가?Exit()는 더 이상 프로그램을 종료하지 않습니까?

nicesource 2023. 4. 9. 21:42
반응형

왜 환경인가?Exit()는 더 이상 프로그램을 종료하지 않습니까?

며칠 전에 발견한 내용인데, 이 질문에서 기계에만 국한된 것이 아니라는 것을 확인했습니다.

Windows Forms 응용 프로그램을 실행하여 버튼을 추가하고 다음 코드를 쓰는 것이 가장 쉬운 방법입니다.

    private void button1_Click(object sender, EventArgs e) {
        MessageBox.Show("yada");
        Environment.Exit(1);         // Kaboom!
    }

Exit() 문이 실행된 후 프로그램이 실패합니다.Windows Forms 에서는 "Error creating window handle" 이 표시됩니다.

관리되지 않는 디버깅을 활성화하면 무슨 일이 일어나고 있는지 어느 정도 알 수 있습니다.COM 모달루프가 실행 중이며 WM_PAINT 메시지를 전달할 수 있습니다.그것은 처분된 형태로는 치명적이다.

내가 지금까지 수집한 사실은 다음과 같다.

  • 이는 단순히 디버거 실행에만 국한된 것이 아닙니다.이것도 1개가 없으면 실패합니다.WER 크래시 대화상자가 두 번 나타납니다.
  • 공정의 bitness와는 관계가 없습니다.wow64 레이어는 매우 악명이 높지만 AnyCPU 빌드는 같은 방식으로 크래시됩니다.
  • 와는 관계가 없습니다.NET 버전 4.5와 3.5는 같은 방법으로 크래시됩니다.
  • 종료 코드는 문제가 되지 않습니다.
  • 호출 스레드Exit()를 호출하기 전에 sleep()을 실행해도 해결되지 않습니다.
  • 이 문제는 64비트 버전의 Windows 8에서 발생하며 Windows 7에서도 동일한 영향을 받지 않는 것으로 보입니다.
  • 이것은 비교적 새로운 행동이어야 합니다. 저는 전에 이런 것을 본 적이 없습니다.Windows Update를 통해 제공되는 관련 업데이트가 없습니다. 단, 업데이트 기록이 더 이상 정확하지 않습니다.
  • 이건 완전히 망가진 행동이야AppDomain 이벤트 핸들러에 이와 같은 코드를 씁니다.Unhandled Exception은 같은 방식으로 크래시됩니다.

이번 사고를 피하기 위해 당신이 할 수 있는 일이 무엇인지 특히 궁금합니다.특히 AppDomain.Unhandled Exception 시나리오에서는 를 종료하는 방법은 많지 않습니다.NET 프로그램어플리케이션에 전화하는 것에 주의해 주세요.Exit() 또는 Form.Close()는 Unhandled Exception 이벤트핸들러에서는 유효하지 않기 때문에 회피책은 아닙니다.


업데이트: Mehrdad는 파이널라이저 스레드가 문제의 일부일 수 있다고 지적했습니다.저는 이것을 본 것 같습니다.또한 CLR이 파이널라이저 스레드에 실행을 완료하도록 지시한2초의 타임아웃에 대한 증거도 보고 있습니다.

파이널라이저는 Native Window 내에 있습니다.ForceExitMessageLoop() 입니다.코드 위치와 거의 일치하는 IsWindow() Win32 함수가 있습니다.머신 코드를 32비트 모드로 볼 때 오프셋 0x3c입니다.IsWindow()가 교착 상태에 있는 것 같습니다.내부 스택 트레이스를 올바르게 취득할 수 없습니다만, 디버거는 P/Invoke 콜이 방금 반환된 것으로 간주합니다.설명하기가 어려워요.더 나은 스택 트레이스를 얻을 수 있다면 보고 싶어요.내 것:

System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.ForceExitMessageLoop() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Finalize() + 0x16 bytes
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12()  + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes

ForceExitMessageLoop 호출 위에는 아무것도 없습니다. 관리되지 않는 디버거가 활성화되어 있습니다.

저는 이 문제에 대해 마이크로소프트에 연락했고, 그것은 효과가 있었던 것 같습니다.적어도 나는 그것이 했다고 생각하고 싶다:)그들에게서 해상도 확인은 받지 못했지만, Windows 그룹은 직접 연락하기 어려워서 중개인을 이용하지 않을 수 없었습니다.

Windows Update를 통해 전달된 업데이트로 문제가 해결되었습니다.크래시 전 눈에 띄는2초의 지연은 없어지고 IsWindow()의 데드록이 해결되었음을 강력히 시사합니다.그리고 프로그램은 깨끗하고 안정적으로 종료됩니다.업데이트는 Windows Defender, wdboot.sys, wdfilter.sys, tcpip.sys, rpcrt4.dll, uxtheme.dll, crypt32.dl 및 wintrust.dlll용 패치를 설치했습니다.

Uxtheme.dll은 홀짝입니다.Visual Styles 테마 API를 구현하여 이 테스트 프로그램에서 사용합니다.확실하진 않지만, 문제의 근원으로서 거기에 내 돈이 걸려 있어요.C:\의 복사WINDOWS\system32에는 버전 번호 6.2.9200.16660이 있으며 2013년 8월 14일에 작성되었습니다.

사건 종결

왜 '더 이상' 작동하지 않는지는 모르겠지만Environment.Exit보류 중인 파이널라이저를 실행합니다. Environment.FailFastDoesn't.

(이상한 이유로) 나중에 실행해야 하는 이상한 보류 중인 피니셔가 있기 때문에 이 문제가 발생할 수 있습니다.

이게 왜 이런 일이 일어나는지 설명해주진 않지만Environment.Exit샘플과 같은 버튼 이벤트 핸들러 - 대신 르네의 답변에 제시된 대로 메인 폼을 닫습니다.

의 경우AppDomain.UnhandledException핸들러, 어쩌면 그냥 세팅만 하면 안 될까?Environment.ExitCode전화하는 것보다Environment.Exit.

난 네가 여기서 뭘 하려고 하는지 잘 모르겠어.Windows Forms 응용 프로그램에서 종료 코드를 반환하는 이유는 무엇입니까?일반적으로 종료 코드는 콘솔애플리케이션에서 사용됩니다.

특히 이 Calling Environment의 크래시를 피하기 위해 무엇을 할 수 있는지 궁금해요.WER 대화 상자가 표시되지 않도록 하려면 Exit()가 필요합니다.

Main 메서드의 try/catch가 있습니까?Windows Forms 어플리케이션의 경우 메시지 루프와 처리되지 않은 예외 핸들러를 항상 테스트/캐치합니다.

저희 앱에서도 같은 문제가 발견되어 다음 구성으로 해결했습니다.

Environment.ExitCode=1;
Application.Exit();

언급URL : https://stackoverflow.com/questions/18036863/why-does-environment-exit-not-terminate-the-program-any-more

반응형