DetailPage-MSS-KB

Base de connaissances

Numéro d'article: 315939 - Dernière mise à jour: mardi 21 novembre 2006 - Version: 4.1

 

Sommaire

Symptômes

Lorsque vous créez un processus enfant à l'aide de la fonction CreateProcess appeler dans un environnement multithread, l'enfant peut hériter des poignées qui n'ont pas destinées à être héritée.

Cause

Ce problème peut se produire si deux threads simultanément créer des processus enfants et rediriger les poignées STD via les canaux. Dans ce scénario, il existe une condition de concurrence lors de la création des canaux et les processus, dans laquelle il est possible pour un enfant à hériter des descripteurs de fichiers destinées à l'autre enfant. Un thread crée les canaux et bien que ce thread soit dans le processus de création du processus, l'autre thread crée également un processus enfant. Toutes les poignées sont pouvant être héritées de l'application au cours de l'appel de CreateProcess sont dupliquées dans pour le processus enfant.

Résolution

Pour contourner ce problème, encapsulez le code création-enfant dans une section critique. Cela empêche toute héritage accidentelle. Pour que cette méthode fonctionne correctement, créer les canaux que noninheritable en définissant le descripteur de sécurité sur la valeur NULL. Ensuite, configurez les extrémités du canal vous souhaitez que l'enfant héritent comme pouvant être héritées à l'aide l'appel de fonction SetHandleInformation , comme illustré dans l'exemple de code suivant :
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);
				
Remarque la solution précédente ne proviennent pas sans les coûts. La création de sections critiques dans le code est parfois en désordre et est fourni à un prix de dégradation des performances. Il existe une autre solution de contournement à ce problème, et elle nécessite la création d'une application intermédiaire pour lancer l'enfant. Toutefois, cette solution a également son inconvénient. Le principal inconvénient de cette méthode est que le parent perd fondamentalement la facilité avec laquelle il obtient code processus. de l'enfant Si le parent a besoin de l'ID de processus, le processus intermédiaire devez lui transmettre en une certaine manière.

En utilisant cette méthode application intermédiaire, vous éviter des héritage accidentel par se fier à Windows pour effectuer le travail pour vous. Des descripteurs accidentellement hérités dans le processus intermédiaire seront certainement pas dupliquées dans à l'enfant. Il est garanti que si vous spécifiez FALSE pour le paramètre bInheritHandles dans l'appel de CreateProcess dans l'application intermédiaire. Vos descripteurs canal seront toujours dupliquées parce que Windows est en toujours en double les poignées STD, même lors bInheritHandles est défini sur FALSE.

Application parent

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

Application intermédiaire

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
}
				

Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft Win32 Application Programming Interface sur le système suivant
    • the operating system: Microsoft Windows XP
    • the operating system: Microsoft Windows 2000
    • Microsoft Windows NT 4.0
Mots-clés : 
kbmt kbapi kbkernbase kbprb kbthread KB315939 KbMtfr
Traduction automatiqueTraduction automatique
IMPORTANT : Cet article est issu du système de traduction automatique mis au point par Microsoft (http://support.microsoft.com/gp/mtdetails). Un certain nombre d’articles obtenus par traduction automatique sont en effet mis à votre disposition en complément des articles traduits en langue française par des traducteurs professionnels. Cela vous permet d’avoir accès, dans votre propre langue, à l’ensemble des articles de la base de connaissances rédigés originellement en langue anglaise. Les articles traduits automatiquement ne sont pas toujours parfaits et peuvent comporter des erreurs de vocabulaire, de syntaxe ou de grammaire (probablement semblables aux erreurs que ferait une personne étrangère s’exprimant dans votre langue !). Néanmoins, mis à part ces imperfections, ces articles devraient suffire à vous orienter et à vous aider à résoudre votre problème. Microsoft s’efforce aussi continuellement de faire évoluer son système de traduction automatique.
La version anglaise de cet article est la suivante: 315939  (http://support.microsoft.com/kb/315939/en-us/ )
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.
Partager
Options de support supplémentaire
Forums du support Microsoft Community
Nous contacter directement
Trouver un partenaire Microsoft Certified Partner
Microsoft Store