2009-05-19 27 views
12

Tenemos un error de larga data en nuestro código de producción. Esto es esencialmente un daemon basado en socket. Escucha un montón de descriptores de archivo usando select.Seleccione EBADF: ¿qué FD es malo?

Ocasionalmente (una vez al día más o menos), seleccionar volverá con EBADF.

He escrito un código para buscar el descriptor de archivo incorrecto, que pasa por encima de cada fd y las llamadas lo seleccionan. Estas llamadas nunca regresan a EBADF. También probé fstat. Ellos tampoco regresan nunca a EBADF.

También reescribí el daemon para usar la encuesta. Esto no ayudó.

¿Alguien tiene alguna otra idea? (Aparte de que cometí un error tonto, que es todo fácil de hacer con seleccionar).

Respuesta

4

Estoy de acuerdo con James. Con poll(), tiene revenciones por fd que se pueden verificar fácilmente.

I.e.

struct pollfd fds[NUM_FDS]; 
int ret, i; 

... 

ret = poll(fds, NUM_FDS, POLL_TIMEOUT); 
for (i = 0; i < NUM_FDS; i++) 
    if (fds[i].revents & POLLHUP || fds[i].revents & POLLNVAL) 
    ... do something ... 

Por supuesto que no lo implementaría de esa manera en el mundo real, es solo un ejemplo. Dejé de usar select() hace mucho tiempo, poll() es una interfaz mucho mejor. Estás en lo cierto, es demasiado fácil dispararse en el pie con select().

4

Lo más probable es que se llame al select en un descriptor de archivo cerrado. La fuente habitual de eso es reutilizar el fd_set sin reiniciarlo. ¿Tiene algo pasando en los controladores de señal? (como volver a abrir un archivo de registro en un HUP?)

3

Si usa poll(), entonces puede revisar los datos y buscar qué error está fallando, que es la gran ventaja.

Cuestiones relacionadas