Partage
  • Partager sur Facebook
  • Partager sur Twitter

Lancer fonction de DLL en multithread

WINAPI Possibilité de séparer contextes mémoires ?

    20 septembre 2017 à 20:55:34

    Salut !

    Je cherche quelque chose particulier.

    J'ai une dll avec un point d'entrée "Compute" disons.

    Pour la charger depuis un programme, j'utilise LoadLibrary, puis GetProcAdress, et je lance la fonction... ça marche.

    Maintenant, je fais des threads avec CreateThread, et je lance donc en parallèle plusieurs fois ma fonction Calcul : ça crash. En débuggant, je vois qu'il y a des variables globales qui ont des valeurs mauvaises : et oui... dans la dll, il y a des variables globales et autres joyeusetés du genre...

    Du coup, j'essaie, dans chaque thread, de faire un LoadLibrary en espérant que les contextes mémoire seront séparés, comme des processus. Non. Même genre de crashs.

    Si je crée un EXE simple qui ne fait que lancer la dll (enfin la fonction Compute), et que j'appelle cet exe depuis mes threads avec CreateProcess, ça marche, ce sont des processus distincts avec chacun leur contexte mémoire, donc ok.

    Mais j'aimerais éviter de trimballer un exe externe.

    Existe t il un moyen de charger une dll avec son propre contexte mémoire, quit à la charger plusieurs fois en parallèle ? Ou bien de faire en sorte que CreateProcess ne lance non pas un exe, mais un point d'entrée de dll ?

    Lancer une fonction de dll comme un processus indépendant.

    Merci de votre lecture :)

    • Partager sur Facebook
    • Partager sur Twitter

    Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

    Anonyme
      20 septembre 2017 à 21:41:25

      Tu pourrais les charger depuis le fichier vers la memoire et ensuite faire le montage PE manuellement, exemple https://github.com/fancycode/MemoryModule

      Edit: Il y a pas mal d'optimisations possibles si tu charges beaucoup de fois la DLL, tu pourrais minimiser le coup de la construction la table d'import, l'initialisation des sections TLS.

      -
      Edité par Anonyme 20 septembre 2017 à 21:49:39

      • Partager sur Facebook
      • Partager sur Twitter
        20 septembre 2017 à 22:28:29

        Fvirtman a écrit:

        Existe t il un moyen de charger une dll avec son propre contexte mémoire, quit à la charger plusieurs fois en parallèle ? Ou bien de faire en sorte que CreateProcess ne lance non pas un exe, mais un point d'entrée de dll ?

        Lancer une fonction de dll comme un processus indépendant.

        Merci de votre lecture :)


        D'après https://stackoverflow.com/questions/5027942/how-to-use-an-old-single-threaded-c-library-in-a-multithreaded-environment

        (dernière réponse david efferman), la solution la plus "simple" serait éventuellement de creer des copies temporaire de la dll (en la renommant donc) et d'y acceder va loadlibrairy/getprocadress? (Le commentaire associé -msalters- j'ai pas compris mais semble une bonne idée )

        • Partager sur Facebook
        • Partager sur Twitter
        ** La doc, c'est comme le PQ: ça sert à se démerder tout seul **
          23 septembre 2017 à 21:44:39

          Salut !

          Merci pour vos réponses, en effet, après quelques recherches, un LoadLibrary de la même dll plusieurs fois dans le même processus ne charge pas plusieurs fois la dll, mais une seule fois. Et donc les variables globales posent un vrai soucis.

          La solution la plus simple est effectivement de faire des copies de la dll, pour leurer Windows, lui dire que c'est 2 dll distinctes, ou alors sinon, reprogrammer un loader complexe comme proposé, mais ça nous emmène loin. 

          Je crois que je vais voir pour faire autrement, quit a faire du multiprocessus. Merci a vous !

          A titre informatif, j'avais codé une version simplifiée de ce que je veux, je poste les codes.

          ladll :

          #include <windows.h>
          #include <stdio.h> 
          
          int globalita = 0;
          
          __declspec( dllimport ) void Test();
          
          void Test()
          {
          	Sleep(100);
          	printf("%d",globalita);
          	Sleep(50);
          	globalita++;
          	Sleep(50);
          	printf("%d",globalita);
          }
          
          

          Et le test :

          #include <windows.h>
          #include <stdio.h>
          #include <stdlib.h>
          
          typedef void (*Func)();
          
          unsigned long WINAPI onethread(void* params)
          {
          	Func f;
          	int param;
          	HMODULE H;
          	param = *(int*)(params);
          	if (param==1)
          		H = LoadLibrary(L"d:\\fred\\testdll\\ladll\\release\\ladll.dll");
          	else
          		H = LoadLibrary(L"d:\\fred\\testdll\\ladll\\Release\\ladll.dll");
          	if (H==NULL)
          		return -1;
          	f = (Func)GetProcAddress(H,"Test");
          	if (f==NULL)
          		return -1;
          	Sleep(30);
          	f();
          	Sleep(1000);
          	FreeLibrary(H);
          	return 0;
          }
          
          int main()
          {
          	HANDLE T1,T2;
          	int a,b;
          	a=1;
          	b=2;
          	T1 = CreateThread(NULL,0,onethread,&a,0,0);
          	Sleep(12);
          	T2 = CreateThread(NULL,0,onethread,&b,0,0);
          	Sleep(2000);
          	return 0;
          }
          


          Les résultats sont 0022, ce qui montre que la variable globale est la même. Si je change une ligne dans le 2e LoadLibrary en appelant ladll2.dll, alors j'ai bien 0011, mais que dans ce cas.

          • Partager sur Facebook
          • Partager sur Twitter

          Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

          Lancer fonction de DLL en multithread

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown