DLL-Funktion mit timer-Loop
-
Martin Richter schrieb:
Nur als Anmerkung: Wobei sich ganz klar verbieter den Thread in DllMain zu starten und zu beenden.
Gegen starten spricht aber nu nixe, bloss darf man nicht drauf warten dass er losläuft...

-
Nein es verbietet sich... hier ist die WinAPI Doku hart und eindeutig. "Must not"!
-
Martin Richter schrieb:
Nein es verbietet sich... hier ist die WinAPI Doku hart und eindeutig. "Must not"!
So kann ich das aber auch nicht direkt finden... Laut Doku darf man alles in kernel32.dll aufrufen, was nicht das laden einer anderen DLL nach sich zieht... somit würde ich CreateThread als "erlaubt" betrachten...
http://msdn2.microsoft.com/en-us/library/ms682583.aspx
-
Jochen Kalmbach schrieb:
somit würde ich CreateThread als "erlaubt" betrachten...
Das schreit geradezu nach Deadlocks! Bekannterweise sind die Aufrufe von DllMain serialisiert. Es kann Dir daher passieren, dass Du damit in DllMain hängen bleibst: Du erzeugst einen Thread, der wiederum DllMain mit DLL_THREAD_ATTACH aufrufen will. Da Du Dich aber gerade schon in DllMain aufhälst, geht das natürlich nicht. Und nein, DisbaleThreadLibraryCalls() ist hier keine Hilfe.
Ebenso ist das doch mit dem Beenden des Threads. Wenn Du den Thread in DllMain startest, wirst Du ihn auch von hier bennden wollen, rate ich mal. In DLL_PROCESS_DETACH signalisierst Du dem Thread das Ende. Wenn Du dann mit WaitForSingleObject auf das tatsächliche Ende wartest, wartest Du mindestens bis Weihnachten 2012.
Also ich halte das wie Martin, mir ist das bei weitem zu gefährlich.
-
Lieber Jochen,
danke für Deinen Beitrag! Du hast mir gerade die Augen geöffnet. Über die von Dir beschriebenen Probleme mit den DLL-Threads bin ich schon kräftig auf's Maul gefallen.
-
@Jochen: Ich habe noch mal nachgesehen. Du hast recht. WinAPI und CreateThread geht. Der Thread wird in jedem Fal erst anlaufen wenn ale bisherigen DllMains abgelaufen sind.
Das es hier zu unangenehmen Deadlock Situationen kommen kann bleibt einfach ein Problem.Das "must not" hing eher mit der MFC zusammen und das schwritte mir bei diesem Thread so durch den Kopf.
Siehe http://support.microsoft.com/kb/142243/en-us
-
Ja wie ich schon sagte, mann kann starten, man darf bloss nicht warten dass er losläuft. Da die MFC letzteres aber tut... geht das mit der MFC halt nicht.
Und Deadlock Probleme sehe ich auch keine, wenn DllMain den Thread wirklich nur lostritt und sonst in keiner Weise angreift, dann wüsste ich nicht wie es irgendwo irgendwie zu einem Deadlock kommen sollte...
-
Ja, ich habe aucn nur von *reinen* WinAPI Lösungen gesprochen. Schoin die Verwendung der CRT innerhalb von DllMain würde ich als sehr kritisch ansehen... (zumindest wenn dynamisch gelinkt; bei statischem Linken wird ja zuerst die DllMain der CRT aufgerufen und dann erst die des "Programmierers".)
-
Jochen Kalmbach schrieb:
Ja, ich habe aucn nur von *reinen* WinAPI Lösungen gesprochen. Schoin die Verwendung der CRT innerhalb von DllMain würde ich als sehr kritisch ansehen... (zumindest wenn dynamisch gelinkt; bei statischem Linken wird ja zuerst die DllMain der CRT aufgerufen und dann erst die des "Programmierers".)
Rüchtüg. Das ist doof. Deswegen muss man da drinnen dann auf *schauder* VirtualAlloc o.ä. zurückgreifen wenn man was "new'en" möchten.
-
Ja wie ich schon sagte, mann kann starten, man darf bloss nicht warten dass er losläuft.
Ich meine aber, daß es ohne warten nicht geht. Du mußt den Thread doch schließlich auch irgendwann kontrolliert beenden, spätestens da wartest Du wieder. Ansonsten sind diese zwei Zeilen eine ziemliche Katastrophe:
HINSTANCE hDll = LoadLibrary(TEXT("MyCool.dll")); FreeLibrary(hDll); // Was macht der gestartete Thread an dieser Stelle?Dann sollte man doch lieber Create/Close Funktionen exportieren und deren Verwendung vorschreiben.
Ich gehe in meiner Paranoia übrigens soweit, als das ich Threads in DLLs erst gar nicht erzeuge, nicht nur nicht in DllMain. Threads erzeuge ich ausschließlich aus der Anwendung heraus und verteile mich auch schon mal auf mehrere Prozesse. Dadurch habe ich immer die volle Kontrolle über die Laufzeit der Threads, und das ganz ohne mögliche Gefahren. Aber ich mache auch noch recht viel mit COM; bekanntlich reicht es, CoUninitialize aufzurufen, um die DLL zu entladen. Wenn dann nicht alle Interfaces released wurden, der Thread noch läuft, au weia...
-
Gästchen schrieb:
Ja wie ich schon sagte, mann kann starten, man darf bloss nicht warten dass er losläuft.
Ich meine aber, daß es ohne warten nicht geht. Du mußt den Thread doch schließlich auch irgendwann kontrolliert beenden, spätestens da wartest Du wieder. Ansonsten sind diese zwei Zeilen eine ziemliche Katastrophe:
HINSTANCE hDll = LoadLibrary(TEXT("MyCool.dll")); FreeLibrary(hDll); // Was macht der gestartete Thread an dieser Stelle?Dann sollte man doch lieber Create/Close Funktionen exportieren und deren Verwendung vorschreiben.
Ich gehe in meiner Paranoia übrigens soweit, als das ich Threads in DLLs erst gar nicht erzeuge, nicht nur nicht in DllMain. Threads erzeuge ich ausschließlich aus der Anwendung heraus und verteile mich auch schon mal auf mehrere Prozesse. Dadurch habe ich immer die volle Kontrolle über die Laufzeit der Threads, und das ganz ohne mögliche Gefahren. Aber ich mache auch noch recht viel mit COM; bekanntlich reicht es, CoUninitialize aufzurufen, um die DLL zu entladen. Wenn dann nicht alle Interfaces released wurden, der Thread noch läuft, au weia...
Was hat das mit irgendwas zu tun? Man kann Threads in DllMain anlegen, fertig aus. Dass das nicht in jeder Situation Sinn macht, bzw. eventuell zu anderen Problemen führen kann ist auch klar -- das muss man sich überlegen wenn man sowas machen möchte.
Die Sache mit FreeLibrary lässt sich relativ einfach regeln, z.B. indem man das entladen der DLL verhindert oder dem Thread seine eigene Referenz auf die DLL gönnt.
-
Bzgl. was alles erlaubt ist:
Hier gibt es von MS eine "Best Practicse":
http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspxUnd da steht:
You should never perform the following tasks from within DllMain:
• Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.
• Synchronize with other threads. This can cause a deadlock.
• Acquire a synchronization object that is owned by code that is waiting to acquire the loader lock. This can cause a deadlock.
• Initialize COM threads by using CoInitializeEx. Under certain conditions, this function can call LoadLibraryEx.
• Call the registry functions. These functions are implemented in Advapi32.dll. If Advapi32.dll is not initialized before your DLL, the DLL can access uninitialized memory and cause the process to crash.
• Call CreateProces. Creating a process can load another DLL.
• Call ExitThread. Exiting a thread during DLL detach can cause the loader lock to be acquired again, causing a deadlock or a crash.
• Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
• Create a named pipe or other named object (Windows 2000 only). In Windows 2000, named objects are provided by the Terminal Services DLL. If this DLL is not initialized, calls to the DLL can cause the process to crash.
• Use the memory management function from the dynamic C Run-Time (CRT). If the CRT DLL is not initialized, calls to these functions can cause the process to crash.
• Call functions in User32.dll or Gdi32.dll. Some functions load another DLL, which may not be initialized.
• Use managed code.