служба windows SIGSEGV

0

Моя служба Windows предоставляет SIGSEGV в конце функции ServiceMain.

Здесь код:

Начало:

int main(int argc, char* argv[])
{

    SrvName[16]=0;
    SERVICE_TABLE_ENTRY servicetable[]=
    {
        {strServiceName,(LPSERVICE_MAIN_FUNCTION)ServiceMain},
        {NULL,NULL}
    };
    BOOL success;
    success=StartServiceCtrlDispatcher(servicetable);
assert(success!=0);
    return(0);
}

Начало обслуживания:

void ServiceMain(DWORD argc, LPTSTR *argv)
{

    BOOL success;
    nServiceStatusHandle=RegisterServiceCtrlHandlerEx(strServiceName,
        (LPHANDLER_FUNCTION_EX)ServiceCtrlHandler, NULL);
assert(nServiceStatusHandle!=0);
success=UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,1,20000);
assert(success!=0);
killServiceEvent=CreateEvent(0,TRUE,FALSE,0);
assert(killServiceEvent!=NULL);

success=UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,2,10000);
assert(success!=0);

nServiceCurrentStatus=SERVICE_RUNNING;
success=UpdateServiceStatus(SERVICE_RUNNING,NO_ERROR,0,0,0);
assert(success!=0);

WaitForSingleObject(killServiceEvent,INFINITE);
CloseHandle(killServiceEvent);

UpdateServiceStatus(SERVICE_STOPPED,NO_ERROR,0,0,0);
return;
}///2x SIGSEGV here

Функция обновления состояния:

BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
        DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
                 DWORD dwWaitHint)
 {
BOOL success;
SERVICE_STATUS nServiceStatus;
nServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
nServiceStatus.dwCurrentState=dwCurrentState;
if(dwCurrentState==SERVICE_START_PENDING)
{
    nServiceStatus.dwControlsAccepted=0;
}
else
{
    nServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP
        |SERVICE_ACCEPT_SHUTDOWN;
}
if(dwServiceSpecificExitCode==0)
{
    nServiceStatus.dwWin32ExitCode=dwWin32ExitCode;
}
else
{
    nServiceStatus.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR;
}
nServiceStatus.dwServiceSpecificExitCode=dwServiceSpecificExitCode;
nServiceStatus.dwCheckPoint=dwCheckPoint;
nServiceStatus.dwWaitHint=dwWaitHint;

success=SetServiceStatus(nServiceStatusHandle,&nServiceStatus);

    return success;
}

Обработчик сообщений SCM:

void ServiceCtrlHandler(DWORD nControlCode,DWORD dwEventType,
LPVOID lpEventData,LPVOID lpContext)
{
switch(nControlCode)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
    nServiceCurrentStatus=SERVICE_STOP_PENDING;
    UpdateServiceStatus(SERVICE_STOP_PENDING,NO_ERROR,0,1,10000);
    SetEvent(killServiceEvent);
    return;
default:
    break;
}
UpdateServiceStatus(nServiceCurrentStatus,NO_ERROR,0,0,0);
return;
}

Итак, у меня есть 2 sigsegv в конце ServiceMain(): "Service.exe вызвал нарушение доступа в местоположении 00000000 Чтение из местоположения 00000000". Регистры:

eax=00000000 ebx=00617d60 ecx=75bd76ba edx=00600174 esi=00000001 edi=00000000
eip=00000000 esp=010eff8c ebp=00617d70 iopl=0         nv up ei pl zr na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246

AddrPC   Params
00000000 00617D60 010EFFD4 77A437EB
7765ED5C 00617D60 70866618 00000000 kernel32.dll!BaseThreadInitThunk
77A437EB 77B47587 00617D60 00000000 ntdll.dll!RtlInitializeExceptionChain
77A437BE 77B47587 00617D60 00000000 ntdll.dll!RtlInitializeExceptionChain

Я использую Code :: Blocks with MinGW, Win7 32bit pro.

У вас есть идеи об этом?

  • 4
    Не ServiceMain . Исправьте фактическую подпись, поставив правильное соглашение о вызовах. AFAIK, все, что использует ваш SERVICE_TABLE_ENTRY , ожидает, что ServiceMain очистит стек, но ServiceMain ожидает, что вышеупомянутая функция очистит его. Похоже, проблема.
  • 1
    При создании службы Windows всегда хорошо иметь способ ее запуска, как обычной не сервисной программы. Таким образом, отладка будет намного проще, поскольку вы можете запустить ее в отладчике.
Показать ещё 3 комментария
Теги:
winapi
sigsegv

1 ответ

1

Все ваши обработчики услуг не имеют __stdcall вызове WINAPI (__stdcall), и ваш HandlerEx также не имеет возвращаемого значения. Эти ошибки вызывают неправильное управление стеком вызовов.

Исправьте свои объявления и избавьтесь от типов. Компилятор выдал бы ошибки о неправильных объявлениях, но вы заставили его игнорировать их и принять ваш плохой код.

SERVICE_TABLE_ENTRY servicetable[]=
{
    {strServiceName, &ServiceMain},
    {NULL,NULL}
};

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
    ...
    nServiceStatusHandle = RegisterServiceCtrlHandlerEx(..., &ServiceCtrlHandler, ...);
    ...
}

DWORD WINAPI ServiceCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
    switch(dwControl)
    {
        case SERVICE_CONTROL_SHUTDOWN:
        case SERVICE_CONTROL_STOP:
            ...
            return NO_ERROR;

        case SERVICE_CONTROL_INTERROGATE:
            ...
            return NO_ERROR;

        default:
            return ERROR_CALL_NOT_IMPLEMENTED;
    }
}
  • 0
    Спасибо за вашу помощь!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню