WSTBoss
Messages postés16Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention27 octobre 2011
-
14 nov. 2008 à 11:43
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 2014
-
18 nov. 2008 à 15:24
Bonjour à tous,
j'ai une dll qui contient un thread, tout ce passe bien le thread marche comme il faut mais cependant lors du dechargement de la dll par l'application, cela génère un exception. J'ai fait pas mal de tests dans tout les sens possible mais la je bloque. Donc je suis revenu au basse et j'ai créé un exe et une dll minimum permettant de reporduire le problème. Pourtant même avec ça, je ne vois pas d'ou viens cette fichue exception. Donc je viens ici avec l'immense espoir que quelqu'un puisse m'aider et me dire ce qui ne va pas. c'est surement pas grand chose mais la j'ai beau ouvrir les yeux, je ne vois rien.
procedure TForm3.Button1Click(Sender: TObject);
var
libHwnd: HWnd;
begin
libHwnd := LoadLibrary('InitDLL.dll');
if libHwnd = 0 then
begin
memo1.Lines.Add('Could not find the dll file!');
EXIT; {EXIT}
end
else
begin
memo1.Lines.Add('dll file find!');
end;
Sleep(1000);
Application.ProcessMessages;
freelibrary(libHwnd);
memo1.Lines.add('Unload OK');
end;
end.
et celui de la dll :
unit myDLL2;
interface
uses
Windows,
SysUtils,
Classes;
type TDllThread = class(TThread)
private
protected
procedure Execute; override;
end;
var
DllThread: TDllThread = NIL;
implementation
procedure TDllThread.Execute();
{-----------------------------------------------------------------------------
Procedure: Execute
Date: 13-nov.-2008
Arguments:
Result: None
Comment:
Comment
-----------------------------------------------------------------------------}
var
i: integer;
begin
i:=0;
{TRAITEMENT}
while (Terminated=False) do
begin
Sleep(10);
Inc(i);
end;
{VALEUR DE RETOUR}
ReturnValue:=1;
end;
cs_rt15
Messages postés3874Date d'inscriptionmardi 8 mars 2005StatutModérateurDernière intervention 7 novembre 201413 17 nov. 2008 à 15:02
Salut,
Heu !
Il y a un problème évident dans ton code...
1 Tu charges une dll.
2 Tu lances un thread qui fait une boucle infinie dans la dll.
3 Tu décharges la dll.
Ca plante. Logique. Comment veux-tu que le thread continue sa boucle infinie si tu décharges sont code ????
Il faut que tu demandes l'arrêt du thread avant de décharger la dll.
-> Ajout d'une fonction exportée par la dll.
-> Cette fonction demande l'arrêt du thread et attend son arrêt effectif.
-> Il faut que le thread soit libéré par cette fonction : le WaitFor ne fonctionne pas si le FreeOnTerminate est à true.
-> Le .exe doit appeler la fonction exportée par la dll avant de décharger celle-ci.
procedure TForm1.Button1Click(Sender: TObject);
var
libHwnd: HWnd;
stopThreadProc: TStopThreadProc;
begin
libHwnd := LoadLibrary('Project2.dll');
if libHwnd = 0 then
begin
memo1.Lines.Add('Could not find the dll file!');
EXIT; {EXIT}
end
else
begin
memo1.Lines.Add('dll file find!');
end;
Sleep(1000);
Application.ProcessMessages;
@stopThreadProc:= GetProcAddress(libHwnd, 'StopThread');
if not Assigned(stopThreadProc) then
begin
memo1.Lines.Add('Could not find StopThread in the dll!');
EXIT; {EXIT}
end;
stopThreadProc();
freelibrary(libHwnd);
memo1.Lines.add('Unload OK');
end;
end.
<hr size="2" width="100%" />unit Unit2;
interface
uses
Windows,
SysUtils,
Classes,
Dialogs;
type TDllThread = class(TThread)
private
protected
procedure Execute; override;
end;
var
DllThread: TDllThread = NIL;
procedure StopThread;
implementation
procedure StopThread;
begin
ShowMessage('Fin du thread');
DllThread.Terminate;
// On attend la fin du thread
DllThread.WaitFor;
DllThread.Free;
end;
procedure TDllThread.Execute();
{-----------------------------------------------------------------------------
Procedure: Execute
Date: 13-nov.-2008
Arguments:
Result: None
Comment:
Comment
-----------------------------------------------------------------------------}
var
i: integer;
begin
i:=0;
{TRAITEMENT}
while (Terminated=False) do
begin
Sleep(10);
Inc(i);
end;
{VALEUR DE RETOUR}
ReturnValue:=1;
end;
WSTBoss
Messages postés16Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention27 octobre 2011 17 nov. 2008 à 15:41
Salut rt15,
merci pour ta réponse, effectivement, je viens de voir ma boulette. En fait, j'ai tellement fait de test que je me suis mélangé les pinceaux. En plus j'ai essayé de faire un code minimal afin de reproduire le bug et du coup, j'ai du supprimer un peux trop vite la ligne dans la section Finalization qui disait DllThread.Terminate;
Du coup, j'ai généré un autre bug que celui que je traquais. Y'a plus qu'a retourner à la pêche...
Sinon, j'avais une question, vaut il mieux utiliser une fonction exporté qui permet d'arréter le thread (comme tu l'as fait) ou mon DllThread.Terminate dans la section Finalization est suffisant ?
merci pour ton aide précieuse. Je retourne chercher le bug qui m'intéresse...
WSTBoss
Messages postés16Date d'inscriptionlundi 16 décembre 2002StatutMembreDernière intervention27 octobre 2011 18 nov. 2008 à 14:49
Salut,
Pour info, si l'on met le terminate et le waitfor dans la section finalization, c'est déjà un peu trop tard pour terminer le thread. cela génère une exception ou le programme ne se ferme pas.
Je prends donc ta méthode d'appeler une fonction d'arrêt du thread avant de décharger la dll.
Cependant que se passe t'il si le programme principal plante et qu'il n'appelle pas la fonction StopThread ?
la dll reste t'elle en mémoire avec le thread qui tourne ?