2009-11-06 13 views
9

Parece que cuando se crea un subproceso desde DllMain en DLL_PROCESS_ATTACH, no comenzará hasta que se hayan cargado todos los dll. Como necesito asegurarme de que el hilo se ejecuta antes de continuar, me sale un punto muerto. ¿Hay alguna manera de forzar el inicio del hilo?Creando un hilo en DllMain?

Respuesta

10

Usted no debe hacer ninguna llamadas a la API, especialmente para cosas como la creación de hilos o ventanas, desde DLLMain. Raymond Chen ha escrito sobre esto muchas veces; aquí está one que es particularmente relevante.

+10

CreateThread es una de las pocas cosas que puede hacer dentro de DllMain, ya que es una llamada a kernel32 que está garantizado que ya está cargado. –

+2

@Ben Voigt, pero tenga mucho cuidado, ya que es fácil obtener un bloqueo muerto si se solicita a la llamada DllMain actual que espere la devolución del nuevo hilo. – mloskot

+0

@mloskot: Llamar a las funciones de espera en 'DllMain' es muy malo sin importar qué tipo de objeto estás esperando. En general, cualquier subproceso que ejecute código desde una DLL necesita tener un recuento de referencia en esa DLL, menos el código que se trazará debajo de ella. Lo que evita que el problema ocurra, ya que 'DllMain' no se llamará (para el proceso de separación) siempre que el hilo se esté ejecutando. –

5

No. No debe llamar CreateThread (o cualquier variación) desde DllMain. Intentar sincronizar dará como resultado un punto muerto. ¿Qué estás tratando de hacer exactamente?

Best Practices for Creating DLLs

+7

No hay nada de malo en llamar a CreateThread, pero no hay forma de evitar el hecho de que el hilo se suspenderá hasta que el proceso DllMain se complete en el hilo principal. –

0

Está pidiendo problemas si hace esto. No debe realizar ninguna llamada (directa o indirectamente) a funciones que estén fuera de su dll (incluidas las llamadas a la biblioteca C, etc.).

Si no puede cambiar el archivo DLL que tiene (por ejemplo, usted no tiene el código fuente), que puede ser que será capaz de salirse con esto si el archivo DLL se carga dinámicamente después de que el resto de su dependiente DLL son inicializado No recomendaría este enfoque si puede evitarlo porque descubrir la cadena de dependencia no siempre es trivial (por ejemplo, si su archivo DLL hace que un dll dependiente cargue un tercero dinámicamente a través de COM o de algún otro modo).

+2

El primer párrafo aquí es una sobre generalización. Está perfectamente bien hacer que las llamadas a archivos DLL que ya conoces ya se hayan cargado antes que las tuyas. En general, y en la mayoría de las situaciones, esto significa solo KERNEL32.DLL, que puede sonar como una limitación paralizante, pero puede usarlo para salir de esta situación. –

+2

http://blogs.msdn.com/oldnewthing/archive/2007/09/04/4731478.aspx –

+0

Gracias Integer Poet. Eso responde exactamente la pregunta que vine aquí a resolver. –

5

¿Qué hace su hilo?

Si intenta mover cosas a un segundo hilo para evitar restricciones sobre lo que puede hacer dentro de DllMain, mala suerte. Esas no son restricciones sobre lo que DllMain puede hacer, son restricciones sobre lo que se puede hacer mientras DllMain se está ejecutando (y mantiene el bloqueo del cargador). Si su hilo necesita tomar el bloqueo del cargador, esperará hasta que el primer hilo termine de usarlo. Si su hilo no necesita el bloqueo del cargador, no veo por qué no podría continuar de inmediato ... pero no existe un hilo que no necesite el bloqueo del cargador. Windows tiene que enviar mensajes DLL_THREAD_ATTACH a todos los archivos DLL antes de que el hilo pueda comenzar a ejecutarse, lo que significa que también llama a su propio DllMain y Windows lo protege contra la reincorporación.

No hay forma de evitar esto. El hilo no puede comenzar hasta después del procesamiento DLL_THREAD_ATTACH, y eso no puede suceder mientras su primer hilo está dentro de DllMain. La única forma de evitarlo es comenzar un nuevo proceso (que tiene un bloqueo de cargador independiente y no bloqueará la espera del suyo).

+0

Intenté un ejercicio simple de usar 'CreateThread()' para una función de trabajador muy simple en 'DLLMain()' durante el procesamiento de un mensaje 'DLL_PROCESS_ATTACH'. La función de subproceso usó 'Sleep()' durante 1000 milisegundos. Todo funcionó bien Pude ver los mensajes 'DLL_THREAD_ATTACH' y' DLL_THREAD_DETACH' tanto del hilo inicial haciendo 'DLL_PROCESS_ATTACH' como del hilo creado durante el proceso de adjuntar. Sin embargo, este subproceso de trabajo no hizo nada más que el 'Sleep()'. Se supone que las llamadas Kernel32.dll están bien. Probado con VS 2005 Windows 7. –

+0

Curiosamente, esta es realmente la única respuesta que responde a la pregunta que se hizo. No sé por qué el OP decidió aceptar una respuesta que no lo es. – IInspectable