2010-07-05 9 views
6

¿Cuáles son las implicaciones de llamar a CloseHandle más de una vez?¿Es seguro "cerrar dos veces" un identificador con CloseHandle?

Los documentos dicen "no deberías", pero creo que tengo un caso realista con canalizaciones con nombre donde un identificador puede cerrarse externamente (ver al final de la publicación).

CloseHandle arroja una excepción en el modo de depuración en este caso, lo que me sugiere a los desarrolladores que esto es grave, pero los documentos no son exactamente claros.

(Solicitud cortés: Por favor, evite la respuesta "¡simplemente no!" :-). Por supuesto, uno debe evitar cerrar un handke más de una vez, y por supuesto hay buenas técnicas para ayudar con esto: estoy interesado en lo que sucede si no lo haces).

He oído que algunas personas sugieren que si el asa reutilizara rápidamente el asa, podría terminar cerrando otro asa diferente.

¿Esto es probable?

¿Cómo elige Windows identificaciones de identificadores?

¿Existe alguna garantía sobre la frecuencia con la que se reutilizará el valor de un asa?

(por ejemplo, TCP garantiza que un número de puerto no se puede reutilizar dentro de un determinado período de tiempo).

¿Se pueden cerrar las manijas entre los tipos de asa? Por ejemplo, ¿podría estar pensando que estoy cerrando una tubería pero terminaré cerrando un evento?

Gracias!

John

(Contexto a esto:. Estoy utilizando canalizaciones con nombre en un modelo cliente/servidor Me parece muy difícil asegurar que exactamente una de las partes está garantizada para cerrar el mango, por ejemplo, en un accidente de proceso/caso muerto. Tal vez estoy equivocado, pero ciertamente el código de ejemplo de MSDN me parece que permite que el cliente cierre el identificador compartido y luego, cuando el servidor intenta cerrarlo, ya está cerrado).

+0

¿A qué "identificador compartido" se está refiriendo? Cada proceso debería crear * y * cerrando su propio identificador a la (misma) tubería. ¿Cómo se comparte un mango? Por desgracia, la respuesta ** es ** "simplemente no", pero eso se debe a que el identificador no debe ser compartido en absoluto. – shambulator

Respuesta

11

lo suficientemente simple para comprobar:

HANDLE h = 0; 
h = CreateMutex(NULL, TRUE, NULL); 
printf("%X\n", h); 
CloseHandle(h); 
h = 0; 
h = CreateMutex(NULL, TRUE, NULL); 
printf("%X\n", h); 

En mi WinXP x64 Esto produjo:

2E8 
2E8 

Así que ahí lo tienen.
A diferencia de los puertos TCP, los identificadores se reciclan inmediatamente.

Repita este experimento con su API favorita o cualquier combinación de las mismas.

+0

+1, también se puede reutilizar un mango para objetos de cualquier tipo, tal vez mutex, quizás otra cosa. Hacer CloseHandle() dos veces podría tener consecuencias sorprendentes. – sharptooth

4

Probablemente tenga una imagen mental incorrecta de una tubería. Tiene dos extremos, cada uno representado por un diferente mango. Sí, se debe llamar a CloseHandle dos veces para que desaparezca la instancia de la tubería. Pero dado que son mangos diferentes, eso nunca puede causar ningún problema. También tenga en cuenta que las instancias de control son específicas del proceso. Incluso si tienen el mismo valor en ambos procesos, no hacen referencia al mismo punto final de la tubería.

+0

Hmm tal vez he entendido mal. Pero definitivamente he visto problemas donde el cliente de la tubería cierra la tubería y el servidor lanza una excepción de "identificador no válido" (en modo de depuración). – John

1

hay dos cosas que podrían suceder:

  1. Se cierra un mango abierto por algún otro código.Probablemente eso no afecte tu código, pero es probable que sea catastrófico para el otro código.
  2. Si está ejecutando un depurador conectado, bloquea su aplicación porque el sistema operativo generará una excepción cuando detecte que se cierra un identificador no válido.

Ninguno de estos es particularmente atractivo en mi humilde opinión.

Cuestiones relacionadas