2013-12-07 2 views
1

나는 다음과 같은 방식으로 작동 내 서비스/클라이언트 프로그램에 심각한 문제가 우연히 발견 한 SERVICE_STOP_PENDING 반환 :SetServiceStatus는 SERVICE_STOPPED을 설정하지만 QueryServiceStatusEx는

  • 클라이언트 앱이 서비스를 중지 ControlService(... SERVICE_CONTROL_STOP ...)를 사용합니다.
  • 서비스가 중지되는 동안 dwCurrentStateSERVICE_STOPPED인지 확인하기 위해 앱에서 주기적으로 QueryServiceStatusEx을 호출합니다. 또한 제한 시간 동안 dwWaitHint을 확인합니다.

는 한편 서비스는이 작업을 수행합니다

  • 청소하기 전에 SetServiceStatusSERVICE_STOP_PENDING = dwCurrentStatedwWaitHint = 3000를 호출합니다.
  • 청소 후 dwCurrentState = SERVICE_STOPPEDdwWaitHint = 0으로 SetServiceStatus을 호출합니다.

재생 및 문제를 로그인 한 후 나는이 함께했다 : 클라이언트가 QueryServiceStatusEx를 호출 = SERVICE_STOP_PENDINGdwCurrentStatedwWaitHint = 0를 반환하는 경우

모든 것이 제외하고 예상 로 마지막 시간을 작동합니다! 그러면 작업 시간이 초과 된 것처럼 동작합니다.

어떻게 이런 일이 일어날 지 모르지만 로그에서 서비스가 종료되기 전에 dwCurrentState = SERVICE_STOPPED으로 설정되었음을 분명히 볼 수 있습니다.

알려진 문제입니까? 여기에 무슨 일이 일어날 지 모른다는 단서가 있습니까?

업데이트 :

다음은 클라이언트 응용 프로그램의 로그 : 당신이 볼 수 있듯이

24437 ssStatus.dwWaitHint: 3000, ssStatus.dwCurrentState: 3 
24546 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3 
24609 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3 
... 
26000 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3 
26062 ssStatus.dwWaitHint: 0, ssStatus.dwCurrentState: 3 
26218 Stopped 

이 서비스가 24437 및 24546 (GetTickCount) 사이에서 중지를하고,이 상태에서 변경된 것 26218입니다. 즉, 1,672 초 동안 SERVICE_STOP_PENDING이라는 플래그가 지정되었습니다. Windows가 상태를 바꿀 수 있습니까? 왜 그렇게 오랫동안 보류 된 것으로 표시 되었습니까?

업데이트 2 :

더 관찰 :

  • SetServiceStatus만큼 서비스의 프로세스가 실행되는 SERVICE_STOP_PENDING로 남겨 dwCurrentState, 제외한 모든 영향을 호출. Windows의 기능입니까? 문서화되어 있습니까?
  • LPSERVICE_MAIN_FUNCTION에서 돌아오고 StartServiceCtrlDispatcher에서 돌아 오기 전에 내 서비스 프로세스가 1 초 이상 지연됩니다. 왜 그런 일이 일어나는거야? (Windows 부팅시 발생합니다).
  • 상태가 SERVICE_STOPPED인데도 서비스 실행 파일에 쓰기를 시도하면 가끔 ERROR_SHARING_VIOLATION이 반환됩니다. 프로세스가 완전히 종료되었는지 확인할 수있는 확실한 방법이 있습니까?

아무도 설명 할 수 있습니까? 레이몬드 첸?

업데이트 3 :

더 흥미로운 정보 : dwWaitHint 반환 QueryServiceStatusEx : 0, dwCurrentState : 3, dwCheckPoint : 0 내가 dwWaitHintdwCheckPoint가 제로로 설정하지 않더라도! 무슨 일 이니?

+0

글쎄, 당신은 그것에 대해 할 수있는 일이 없으니 문제를 해결하십시오. dwWaitHint는 정지 상태에서는 의미가 없으므로 변경하지 마십시오. –

+0

MS가 그들의 [예제] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb540475%28v=vs.85%29.aspx) ("ReportSvcStatus (SERVICE_STOPPED, NO_ERROR, 0); "), 그리고 내 애플 리케이션, 따라서 행동을 기반으로합니다. 몇 가지 추가 로깅을 수행하고 질문을 업데이트했습니다. – Paul

+0

서비스가 SERVICE_STOPPED 및 ServiceMain 종료 중으로 설정하는 중 일부 작업을하고있는 것 같습니다. 어쩌면 ServiceMain 함수의 지역 변수에 뿌리를 둔 상태 더미가있을 수 있습니다. 따라서 함수가 완전히 종료되면 소멸자에서 정리되고 있습니까? – arx

답변

1

간단한 서비스를 만들고 서비스 자체에서 서비스 상태를 쿼리하여 쿼리가 상태 변경과 동기화되도록했습니다.

SCM이 서비스를 중지하도록 요청했습니다. 쿼리 된 상태는 SERVICE_RUNNING입니다. 이 서비스는 상태를 SERVICE_STOPPED로 설정하고 다시 쿼리 한 다음 SERVICE_STOP_PENDING을받습니다 (대기 힌트는 0입니다). 마지막으로 서비스는 StartServiceCtrlDispatcher가 반환 된 후 상태를 쿼리하고 SERVICE_STOPPED를 받았습니다.

이것은 완전히 일치하지는 않습니다.

SERVICE_RUNNING, SERVICE_STOP_PENDING 및 SERVICE_STOPPED 또는

SERVICE_RUNNING, SERVICE_STOPPED 및 SERVICE_STOPPED : 세 개의 쿼리에 대한 두 가지 결과가있다.

sc 명령 줄 도구에서 같은 것을 볼 수 있습니다. 서비스 중단을 요청하면 상태가 중지 된 것으로보고하고 때로는 보류 상태로보고합니다. 서비스가 보류 상태로 설정되지는 않습니다.

서비스가 상태를 SERVICE_STOPPED로 설정 한 후 Windows가 발송자 (주) 스레드로 제어를 반환하기 직전에 간단한 SERVICE_STOP_PENDING 창이 나타납니다. 컴퓨터가 부팅되어 바쁜 경우 SERVICE_STOP_PENDING의이 창이 상당히 길 수 있습니다.

동작은 재현 가능하며 의도적 인 것으로 보입니다. 그러나, 당신이 말했듯이, 그것은 어디에도 문서화되어 있지 않습니다.

+0

분석해 주셔서 감사합니다. 최선의 해결책은 수비가되는 것입니다. 더 이상 지연 힌트로만 'dwWaitHint'를 시간 초과 값으로 간주하지 않습니다. 나는이 뉘앙스를 어려운 방법으로 발견해야만한다. 내 코드는 MSDN의 예제를 기반으로했습니다. MSDN이 아닌 경우 어디에서 올바른 스 니펫을 가져야합니까? – Paul

관련 문제