PROBLEMA: Subordinado herda identificadores inesperados durante a chamada de CreateProcess

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
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}				

Aviso: Este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 315939 - Última Revisão: 11/21/2006 15:37:38 - Revisão: 4.1

Microsoft Win32 Application Programming Interface

  • kbmt kbapi kbkernbase kbprb kbthread KB315939 KbMtpt
Comentários