DetailPage-MSS-KB

Base de Dados de Conhecimento

ID do artigo: 315939 - Última revisão: terça-feira, 21 de novembro de 2006 - Revisão: 4.1

 

Nesta página

Sintomas

Quando você cria um processo filho usando a função CreateProcess chamar em um ambiente multithreaded, a criança pode herdar alças que não foram se destina a ser herdada.

Causa

Esse comportamento pode ocorrer se dois threads simultaneamente criem processos filho e redirecionar as alças de DESVPAD por meio de pipes. Nesse cenário, há uma condição de corrida durante a criação dos pipes e dos processos, no qual é possível para um filho herdar identificadores de arquivo destinados-se a outro filho. Um thread cria os pipes e enquanto esse thread está no processo de criação do processo, outro segmento também está criando um processo filho. Todos os identificadores são herdáveis no aplicativo durante a chamada de CreateProcess são duplicados entre o processo filho.

Resolução

Para contornar esse problema, coloque o código de criação de filho em uma seção crítica. Isso impede que qualquer herança acidental. Para esse método funcione corretamente, crie os pipes como noninheritable definindo o descritor de segurança como NULL. Em seguida, defina as extremidades da conexão que você deseja o filho para herdar como herdáveis usando a chamada de função SetHandleInformation , conforme demonstrado no código de exemplo a seguir:
CRITICAL_SECTION    cs;
HANDLE              hReadIn, hWriteIn;
HANDLE              hReadOut, hWriteOut;
HANDLE              hReadErr, hWriteErr;

InitializeCriticalSection(&cs);

EnterCriticalSection(&cs);

if ( !CreatePipe(&hReadIn, &hWriteIn, NULL, 0) )
{
    // an error occurred
}

if ( !CreatePipe(&hReadOut, &hWriteOut, NULL, 0) )
{
    // an error occurred
}

if ( !CreatePipe(&hReadErr, &hWriteErr, NULL, 0) )
{
    // an error occurred
}

if ( !SetHandleInformation(hReadIn, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) )
{
    // an error occurred
}

if ( !SetHandleInformation(hWriteOut, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) )
{
    // an error occurred
}

if ( !SetHandleInformation(hWriteErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) )
{
    // an error occurred
}

STARTUP_INFO        si;
PROCESS_INFORMATION pi;

si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = hReadIn;
si.hStdOutput = hWriteOut;
si.hStdError = hWriteErr;

if ( !CreateProcess( "child.exe",
                     NULL,
                     NULL, NULL,
                     TRUE,
                     NORMAL_PRIORITY_CLASS,
                     lpEnvironment,
                     &si, &pi) )
{
    // an error occurred
}

CloseHandle(hReadIn);
CloseHandle(hWriteOut);
CloseHandle(hWriteErr);

LeaveCriticalSection(&cs);
				
Observação que a solução anterior não vem sem custos. A criação de seções críticas no código, às vezes, é confusa e tem um preço de degradação do desempenho. Há outra solução alternativa para esse problema, e ele requer a criação de um aplicativo intermediário para iniciar o filho. No entanto, essa solução também tem a desvantagem. A principal desvantagem desse método é que o pai basicamente perde a facilidade com o qual ele obtém a identificação do processo. da criança Se o pai precisa a identificação do processo, o processo intermediário deve passar para ele volta alguma forma.

Usando esse método intermediário de aplicativo, você pode evitar qualquer herança acidental baseando-se no Windows para fazer o trabalho para você. Os identificadores herdados acidentalmente no processo de intermediário serão definitivamente não duplicados entre para o filho. Isso é garantido que se você especificar FALSO para o parâmetro bInheritHandles na chamada para CreateProcess no aplicativo intermediário. Seus identificadores de pipe ainda serão duplicados porque o Windows sempre duplicar identificadores STD, mesmo quando bInheritHandles está definida como FALSE.

Aplicativo pai

HANDLE              hReadIn, hWriteIn;
HANDLE              hReadOut, hWriteOut;
HANDLE              hReadErr, hWriteErr;

if ( !CreatePipe(&hReadIn, &hWriteIn, NULL, 0) )
{
    // an error occurred
}

if ( !CreatePipe(&hReadOut, &hWriteOut, NULL, 0) )
{
    // an error occurred
}

if ( !CreatePipe(&hReadErr, &hWriteErr, NULL, 0) )
{
    // an error occurred
}

STARTUP_INFO        si;
PROCESS_INFORMATION pi;

si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = hReadIn;
si.hStdOutput = hWriteOut;
si.hStdError = hWriteErr;

if ( !CreateProcess( "Intermediate.exe",
                     NULL,
                     NULL, NULL,
                     TRUE,
                     NORMAL_PRIORITY_CLASS,
                     lpEnvironment,
                     &si, &pi) )
{
    // an error occurred
}

CloseHandle(hReadIn);
CloseHandle(hWriteOut);
CloseHandle(hWriteErr);
				

Aplicativo intermediário

STARTUP_INFO        si;
PROCESS_INFORMATION pi;

si.cb = sizeof(si);

if ( !CreateProcess( "child.exe",
                     NULL,
                     NULL, NULL,
                     FALSE,
                     NORMAL_PRIORITY_CLASS,
                     lpEnvironment,
                     &si, &pi) )
{
    // an error occurred
}
				

A informação contida neste artigo aplica-se a:
  • Interface de Programação de Aplicativos do Microsoft Win32 nas seguintes plataformas
    • the operating system: Microsoft Windows XP
    • the operating system: Microsoft Windows 2000
    • Microsoft Windows NT 4.0
Palavras-chave: 
kbmt kbapi kbkernbase kbprb kbthread KB315939 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 315939  (http://support.microsoft.com/kb/315939/en-us/ )
Compartilhar
Opções de suporte adicionais
Fóruns de Suporte do Microsoft Community
Contate-nos diretamente
Localize um parceiro certificado da Microsoft
Microsoft Store