2012-03-25 37 views
5

¿Es seguro si deseo llamar a closesocket() en un socket de servidor de 1 hilo que está separado de otro hilo que ejecuta el servidor usando el mismo socket de servidor?¿Es seguro el hilo cerrado?

+2

Es posible que desee volver a pensar * por qué * tiene varios subprocesos que acceden al mismo socket. Tal vez sería mejor tener algún indicador de estado que pueda * informar * a los otros hilos que una conexión está muriendo, pero que solo un hilo realmente interactúe con el socket. –

+0

@KerrekSB: por lo general, hay más de un subproceso que accede al socket porque un subproceso realiza lecturas de bloqueo y escribe otro subproceso. Esto es seguro/normal. Un indicador de estado no es útil si el/los thread (s) están bloqueados al bloquear llamadas. –

+0

@MartinJames: aunque esa práctica es "segura" desde el punto de vista del zócalo, es muy difícil tener ese escenario correcto (al menos, es mucho más difícil de lo que parece a primera vista), precisamente porque hay una gran dificultad para sincronizar hilos que están atrapados en una llamada de bloqueo. En cualquier caso, el diseño de la aplicación debería dejar en claro a quién pertenece el zócalo, y "quien termine último" es realmente una buena opción. –

Respuesta

5

La llamada en sí es segura para subprocesos, pero la práctica no lo es. Siempre que desasigne un recurso cuyo identificador podría reutilizarse después de desasignarse, debe sincronizar con todos los hilos que posiblemente puedan usarlo. De lo contrario, es posible que, después de desasignar el recurso, se pueda asignar un nuevo recurso (en su caso, socket) con el mismo identificador (número de socket), y el código que tenga la intención de acceder al socket del servidor (ahora cerrado) pueda terminar funcionando en un zócalo diferente.

El grado en que esto es peligroso (y si puede suceder en absoluto) depende en gran medida de su código. Puede que no ocurra si nunca crea más sockets después de cerrar el socket del servidor. Pero todavía está conceptualmente muy mal, y cualquier persona competente que revise su código lo consideraría muy malo.

Editar: La solución a problemas como este es la protección del descriptor de recursos (no el recurso en sí) con un bloqueo de lector-escritor (rwlock). Acceder al descriptor de recursos (la variable entera que contiene el número de socket, en su caso) requiere mantener un bloqueo de "lectura", ya sea que esté realizando una entrada o salida u otra operación utilizando el recurso al que hace referencia. La desasignación del recurso (y el almacenamiento de un valor centinela como -1 en la variable que contiene el descriptor) requiere un bloqueo de escritura.

+0

Para eso es 'TIME_WAIT'. Si hay algún mapeo de nivel superior (por ejemplo, una biblioteca de sockets asigna un objeto de contexto de socket) y no se asegura de que dichos contextos no puedan ser reutilizados, eso no está dentro del alcance de la pregunta de OP. Si se considera que este enfoque es incorrecto, entonces tal vez alguien quiera sugerir una alternativa (una que no implique un rediseño de un servidor de sincronización como sincronización y no requiera tiempos de espera cortos de CPU en el socket para verificar un indicador). –

+1

No, no tiene ninguna relación con 'TIME_WAIT'. No estoy hablando de que * port * se reutilice, lo que no es problema. Estoy hablando del * socket number * (en POSIX esto sería un descriptor de archivo, pero en Windows están separados), que es un entero local del proceso que identifica un socket abierto, siendo reutilizado. Esto no tiene absolutamente nada que ver con 'TIME_WAIT'. –

+0

Está relacionado, aunque no directamente. Es un recurso en el que posiblemente existan dudas sobre cuándo puede reutilizarse.Una forma común de resolver este problema es colocar el recurso en una cola de temporizador hasta que exista una probabilidad razonable de que la reutilización pueda causar un problema (TCP TIME_WAIT). En el caso de los mangos de socket, el problema suele ser incluso fácil de controlar sin tiempos de espera, por ej. quitando la manija de la lista segura a la que pertenece. El hecho de que algo pueda ser mal usado no significa que uno nunca deba hacerlo, especialmente si no hay una alternativa razonable. –

1

Sí, no es un problema. Naturalmente, habrá excepciones/errores generados en el otro/s thread/s que tienen llamadas pendientes en el socket, pero la pila de red en sí misma (que debe ser thread-safe debido a todos los diferentes procesos/hilos que normalmente lo usan), no se dañará.

Cuestiones relacionadas