42 передается в TerminateProcess, иногда GetExitCodeProcess возвращает 0 - PullRequest
3 голосов
/ 14 января 2010

После того как я получил дескриптор, возвращенный CreateProcess, я вызываю TerminateProcess, передавая 42 для кода завершения процесса. Затем я использую WaitForSingleObject для завершения процесса и, наконец, вызываю GetExitCodeProcess.

Ни одна из функций не вызывает сообщения об ошибках. Дочерний процесс является бесконечным циклом и не завершается сам по себе.

Проблема в том, что иногда GetExitCodeProcess возвращает 42 для кода выхода (как и должно быть), а иногда возвращает 0. Есть идеи, почему?

#include <string>
#include <sstream>
#include <iostream>
#include <assert.h>
#include <windows.h>

void check_call( bool result, char const * call );
#define CHECK_CALL(call) check_call(call,#call);

int
main( int argc, char const * argv[] )
    {
    if( argc>1 )
        {
        assert( !strcmp(argv[1],"inf") );
        for(;;)
            {
            }
        }
    int err=0;
    for( int i=0; i!=200; ++i )
        {
        STARTUPINFO sinfo;
        ZeroMemory(&sinfo,sizeof(STARTUPINFO));
        sinfo.cb=sizeof(STARTUPINFO);
        PROCESS_INFORMATION pe;
        char cmd_line[32768];
        strcat(strcpy(cmd_line,argv[0])," inf");
        CHECK_CALL((CreateProcess(0,cmd_line,0,0,TRUE,0,0,0,&sinfo,&pe)!=0));
        CHECK_CALL((CloseHandle(pe.hThread)!=0));
        CHECK_CALL((TerminateProcess(pe.hProcess,42)!=0));
        CHECK_CALL((WaitForSingleObject(pe.hProcess,INFINITE)==WAIT_OBJECT_0));
        DWORD ec=0;
        CHECK_CALL((GetExitCodeProcess(pe.hProcess,&ec)!=0));
        CHECK_CALL((CloseHandle(pe.hProcess)!=0));
        err += (ec!=42);
        }
    std::cout << err;
    return 0;
    }

std::string
get_last_error_str( DWORD err )
    {
    std::ostringstream s;
    s << err;
    LPVOID lpMsgBuf=0;
    if( FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
            0,
            err,
            MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
            (LPSTR)&lpMsgBuf,
            0,
            0) )
        {
        assert(lpMsgBuf!=0);
        std::string msg;
        try
            {
            std::string((LPCSTR)lpMsgBuf).swap(msg);
            }
        catch(
        ... )
            {
            }
        LocalFree(lpMsgBuf);
        if( !msg.empty() && msg[msg.size()-1]=='\n' )
            msg.resize(msg.size()-1);
        if( !msg.empty() && msg[msg.size()-1]=='\r' )
            msg.resize(msg.size()-1);
        s << ", \"" << msg << '"';
        }
    return s.str();
    }

void
check_call( bool result, char const * call )
    {
    assert(call && *call);
    if( !result )
        {
        std::cerr << call << " failed.\nGetLastError:" << get_last_error_str(GetLastError()) << std::endl;
        exit(2);
        }
    }

Ответы [ 3 ]

1 голос
/ 15 января 2010

Я думал, что в комментарии Нобагза это было прибито ...

Но вот еще одна дикая догадка - может быть, вы звоните TerminateProcess() слишком скоро вместо того, чтобы слишком поздно, и Windows не совсем сериализует установку кода ошибки процесса, указанного TerminateProcess(), независимо от того, что пытаться делать при инициализации процесса? Я думаю, что это маловероятно, но, возможно, стоит добавить в Sleep(1) вызов, который Сет предложил (или даже Sleep(0)), чтобы посмотреть, изменится ли поведение.

Кроме того, вы можете рассмотреть возможность размещения некоторого кода, с которым люди могут экспериментировать.

1 голос
/ 08 марта 2010

Пожалуйста, прочитайте это и это .

По сути, функция TerminateProcess - это ужасный беспорядок, которого следует избегать. Используйте его на свой страх и риск.

Если это вообще возможно, следует использовать другой механизм для остановки вашего процесса.

0 голосов
/ 15 января 2010

Из документов GetExitCodeProcess:

Если функция не работает, возвращаемое значение равно нулю. Чтобы получить расширенную информацию об ошибке, вызовите GetLastError.

От: http://msdn.microsoft.com/en-us/library/ms683189(VS.85).aspx

Я бы порекомендовал позвонить GetLastError(), чтобы посмотреть, что сломалось. Возможно, вы захотите добавить в свой цикл sleep(1): P

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...