DetailPage-MSS-KB

Base de Dados de Conhecimento

Artigo: 315939 - Última revisão: terça-feira, 21 de Novembro de 2006 - Revisão: 4.1

 

Nesta página

Sintomas

Quando cria um processo subordinado utilizando a função de CreateProcess chamada num ambiente com vários threads, a criança pode herdar alças que não foram se destina a ser herdadas.

Causa

Este comportamento pode ocorrer se dois threads simultaneamente criar processos subordinados e redireccionar as alças de STD através de pipes. Neste cenário, existe uma condição de corrida durante a criação de pipes e processos, no qual é possível para uma criança herdar identificadores de ficheiro destinados a criança. Um thread cria os pipes e enquanto esse thread está no processo de criar o processo, o thread também está a criar um processo de subordinados. Todos os identificadores são herdáveis da aplicação durante a chamada de CreateProcess são duplicados ao processo de subordinados.

Resolução

Para contornar este problema, molde o código de criação do subordinado de uma secção crítica. Isto impede que qualquer herança acidental. Para este método funcione correctamente, crie os pipes como noninheritable definindo o descritor de segurança para NULL. Em seguida, defina as extremidades do pipe que pretende que a criança para herdar como herdável utilizando a chamada de função SetHandleInformation , tal como demonstrado no seguinte código de exemplo:
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);
				
Note que a solução anterior não fica sem custos. A criação de secções críticas no código, por vezes, é confusas e fornecido a um preço de diminuição de desempenho. Existe outra solução para este problema e requer a criação de uma aplicação intermédia para iniciar o subordinado. No entanto, esta solução também tem a desvantagem. A principal desvantagem deste método é que o principal basicamente perde a facilidade com que obtém a ID do processo. da criança Se o principal tiver o ID do processo, o processo intermédio tem transmiti-las novamente alguma forma.

Utilizando este método de aplicação intermédio, evitar qualquer herança acidental, depender do Windows para fazer o trabalho por si. Quaisquer identificadores acidentalmente herdadas do processo intermédio serão definitivamente não duplicados ao longo da criança. Isto é garantido que se especificar FALSO para o parâmetro bInheritHandles na chamada para CreateProcess na aplicação intermédia. As alças de encaminhamento (pipe) ainda serão duplicadas porque o Windows irá sempre duplicar alças STD, mesmo quando bInheritHandles está definida como FALSE.

Aplicação principal

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);
				

Aplicação intermédia

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:
  • Microsoft Win32 Application Programming Interface 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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática… erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes 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/ )
Partilhar
Opções de suporte adicionais
Fóruns de Suporte da Comunidade Microsoft
Contacte-nos directamente
Encontre um parceiro certificado Microsoft
Loja Microsoft