pthread_join pthread_exit pthread_create pthread c linux multithreading posix

pthread_exit - ¿Qué hace Select(2) si cierra(2) un descriptor de archivo en un hilo separado?



pthreads php (4)

Es un poco confuso lo que estás preguntando ...

Select () debería volver tras un cambio "interesante". Si el cierre () simplemente disminuía el recuento de referencias y el archivo aún estaba abierto para escribir en algún lugar, entonces no hay ninguna razón para que select () se active.

Si el otro subproceso se cerró () en el único descriptor abierto, entonces se vuelve más interesante, pero necesitaría ver una versión simple del código para ver si algo está realmente mal.

¿Cuál es el comportamiento de la función select(2) cuando un descriptor de archivo que está mirando para leer está cerrado por otro hilo?

De alguna prueba superficial, regresa de inmediato. Sospecho que el resultado es que (a) todavía continúa esperando datos, pero si realmente intentas leer de él obtendrás EBADF (posiblemente - hay una carrera potencial) o (b) que pretende ser como si el descriptor de archivo nunca se pasó. Si el último caso es cierto, pasar un solo fd sin tiempo de espera provocaría un interbloqueo si se cerrase.


Esperaría que se comportaría como si se hubiera alcanzado el final del archivo, es decir, volvería con el descriptor de archivo mostrado como listo, pero cualquier intento de leerlo posteriormente devolvería el "descriptor de archivo incorrecto".

Habiendo dicho eso, hacer eso es una mala práctica, ya que siempre tendrías posibles condiciones de carrera ya que otro descriptor de archivo con el mismo número podría abrirse con otro hilo inmediatamente después de que el segundo lo cerrara, entonces el hilo de selección terminaría esperando en el equivocado.

Tan pronto como cierre un archivo, su número estará disponible para su reutilización, y puede volver a ser utilizado por la siguiente llamada para abrir (), socket (), etc., incluso si está en otro hilo. Por lo tanto, realmente, realmente debes evitar este tipo de cosas.


La llamada al sistema de selección es una forma de esperar a que los descodificadores de archivos cambien de estado mientras que los programas no tienen nada más que hacer. El uso principal es para aplicaciones de servidor, que abren una gran cantidad de descriptores de archivos y luego esperan que ocurra algo sobre ellos (acepte nuevas conexiones, lea solicitudes o envíe las respuestas). Esos descriptores de archivos se abrirán en modo no bloqueante, de modo que el proceso del servidor no se bloqueará en un syscall en ningún momento.

Esto significa, además, que no hay necesidad de hilos separados, porque todo el trabajo que se podría hacer en el hilo también se puede hacer antes de la llamada de selección. Y si el trabajo lleva mucho tiempo, que puede ser interrumpido, seleccione ser llamado con timeout = {0,0}, se manejan los descriptores de archivo y luego se reanuda el trabajo.

Ahora, cierra un descriptor de archivo en otro hilo. ¿Por qué tiene ese hilo adicional y por qué cerrará el descriptor del archivo?

El estándar POSIX no proporciona ninguna pista, lo que sucede en este caso, entonces lo que está haciendo es COMPORTAMIENTO INDEFINIDO. Espere que el resultado sea muy diferente entre diferentes sistemas operativos e incluso entre versiones del mismo sistema operativo.

Saludos, Bodo


De alguna investigación adicional, parece que tanto el dwc como bothie tienen razón.

La respuesta de Bothie a la pregunta se reduce a: es un comportamiento indefinido. Eso no significa que sea impredecible necesariamente, sino que diferentes sistemas operativos lo hacen de manera diferente. Parece que los sistemas como Solaris y HP-UX regresan de select(2) en este caso, pero Linux no se basa en esta publicación en la lista de correo de linux-kernel de 2001.

El argumento en la lista de correo de Linux-kernel es esencialmente que es un comportamiento indefinido (y roto) en el que se puede confiar. En el caso de Linux, al llamar a close(2) en el descriptor de archivo se reduce efectivamente el recuento de referencias. Como hay una llamada select(2) también con una referencia a ella, el fd permanecerá abierto y esperando la entrada hasta que regrese el select(2) . Esta es básicamente la respuesta de dwc . Obtendrá un evento en el descriptor del archivo y luego se cerrará. Intentar leer de él dará como resultado un EBADF, suponiendo que el fd no se haya reciclado. (Una preocupación que MarkR hizo en su respuesta , aunque creo que probablemente sea evitable en la mayoría de los casos con la sincronización adecuada).

Así que gracias a todos por la ayuda.