Le premier thread qui s’exécute dans un processus Win32 est-il le « thread principal » ?Besoin de comprendre la sémantique

StackOverflow https://stackoverflow.com//questions/9695370

Question

Je crée un processus en utilisant CreateProcess() avec le CREATE_SUSPENDED puis continuez en créant un petit patch de code à l'intérieur du processus distant pour charger une DLL et appeler une fonction (exportée par cette DLL), en utilisant VirtualAllocEx() (avec ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE), WriteProcessMemory(), puis appelle FlushInstructionCache() sur ce morceau de mémoire avec le code.

Après ça j'appelle CreateRemoteThread() pour invoquer ce code, me créant un hRemoteThread.J'ai vérifié que le code à distance fonctionne comme prévu. Note: ce code renvoie simplement, il n'appelle aucune API autre que LoadLibrary() et GetProcAddress(), suivi de l'appel de la fonction stub exportée qui renvoie actuellement simplement une valeur qui sera ensuite transmise comme état de sortie du thread.

Vient maintenant l’observation étrange :rappelez-vous que le PROCESS_INFORMATION::hThread est toujours suspendu.Quand j'ignore simplement hRemoteThreadet n'attendez pas non plus qu'il se termine, tout se passe "bien".La routine qui appelle CreateRemoteThread() les retours et PROCESS_INFORMATION::hThread est repris et le programme (à distance) peut réellement s'exécuter.

Cependant, si j'appelle WaitForSingleObject(hRemoteThread, INFINITE) ou procédez comme suit (ce qui a le même effet) :

DWORD exitCode = STILL_ACTIVE;
while(STILL_ACTIVE == exitCode)
{
    Sleep(500);
    if(!GetExitCodeThread(hRemoteThread, &exitCode))
        break;
}

suivi de CloseHandle() cela mène à hRemoteThread terminer avant PROCESS_INFORMATION::hThread est repris et le processus « disparaît » simplement.Il suffit de permettre hRemoteThread finir d'une manière ou d'une autre sans PROCESS_INFORMATION::hThread pour provoquer la mort du processus.

Cela ressemble étrangement à une condition de concurrence critique, puisque dans certaines circonstances hRemoteThread peut encore être plus rapide et le processus "disparaîtra probablement", même si je laisse le code tel quel.

Cela implique-t-il que le premier thread exécuté dans un processus devient automatiquement le thread principal et qu'il existe des règles spéciales pour ce thread principal ?

J'ai toujours eu l'impression qu'un processus se termine lorsque son dernier thread meurt, et non lorsqu'un particulier le fil meurt.

A noter également : il n'y a pas d'appel à ExitProcess() impliqué ici de quelque manière que ce soit, parce que hRemoteThread revient simplement et PROCESS_INFORMATION::hThread est toujours suspendu quand j'attends hRemoteThread rendre.

Cela se produit sous Windows XP SP3, 32 bits.

Modifier: Je viens d'essayer Sysinternals Process Monitor pour voir ce qui se passe et j'ai pu vérifier mes observations d'avant.Le code injecté ne plante pas ou quoi que ce soit, mais je constate que si je n'attends pas le thread, il ne se ferme pas avant de fermer le programme dans lequel le code a été injecté.Je me demande si l'appel à CloseHandle(hRemoteThread) devrait être reporté ou quelque chose comme ça...

Édition+1 : ce n'est pas CloseHandle().Si je laisse cela de côté juste pour un test, le comportement ne change pas en attendant la fin du fil.

Était-ce utile?

La solution

Le premier thread à exécuter n’est pas spécial.

Par exemple, créez une application console qui crée un thread suspendu et met fin au thread d'origine (en appelant ExitThread).Ce processus ne se termine jamais (sous Windows 7 en tout cas).

Ou faites attendre le nouveau fil de discussion pendant cinq secondes, puis quittez-le.Comme prévu, le processus durera cinq secondes et se terminera à la fin du thread secondaire.

Je ne sais pas ce qui se passe avec votre exemple.Le moyen le plus simple d'éviter la course est de faire en sorte que le nouveau fil de discussion reprenne le fil d'origine.

En spéculant maintenant, je me demande si ce que vous faites ne risque pas de causer des problèmes de toute façon.Par exemple, qu'arrive-t-il à tous les DllMain appelle les DLL chargées implicitement ?Se produisent-ils de manière inattendue sur le mauvais thread, sont-ils ignorés ou sont-ils reportés jusqu'à ce que votre code soit exécuté et que le thread principal démarre ?

Autres conseils

Il y a de fortes chances que le fil avec le main (ou équivalent) appels de fonction ExitProcess (soit explicitement, soit dans sa bibliothèque d'exécution). ExitProcess, eh bien, quitte tout le processus, y compris la suppression de tous les threads.Puisque le thread principal ne connaît pas votre code injecté, il n’attend pas qu’il se termine.

Je ne sais pas s'il existe un bon moyen de faire attendre le fil de discussion principal que le vôtre soit terminé...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top