Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

365
Views
getifaddrs devolviendo 'descriptor de archivo incorrecto'/bloqueando la aplicación

En mi programa, tengo un hilo que tiene que monitorear continuamente las interfaces de red, por lo tanto, usa continuamente getifaddrs() en un ciclo while.

 while(true) { struct ifaddrs *ifaddr, *ifa; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs couldn't fetch required data"); exit(EXIT_FAILURE); } //Iterate through interfaces linked list for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { //monitoring logic } //Free linked list freeifaddrs(ifaddr); //Sleep for specified time fo next polling cycle usleep(1000); }

La mayoría de las veces mi programa funciona bien. Sin embargo, a veces getifaddrs() devuelve -1 y errNo = EBADF(bad file descriptor) . Para no salir de mi hilo, he reemplazado temporalmente salir con continuar (ya que no quiero que mi programa finalice debido a esto). Sin embargo, tengo curiosidad por saber en qué casos puede getifaddrs() devolver el error 'descriptor de archivo incorrecto' y si puedo hacer algo para que esto no suceda.

EDITAR

reemplazar 'salir' con 'continuar' no resolvió mi problema. ¡A veces, la llamada a getifaddrs() bloquea la aplicación!

A continuación se muestra el seguimiento obtenido de gdb utilizando el archivo central generado.

 Program terminated with signal 6, Aborted. #0 0x00007fe2df1ef387 in raise () from /lib64/libc.so.6 Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-37.el7_6.x86_64 libcom_err-1.42.9-16.el7.x86_64 libgcc-4.8.5-39.el7.x86_64 libselinux-2.5-14.1.el7.x86_64 libstdc++-4.8.5-39.el7.x86_64 openssl-libs-1.0.2k-19.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-18.el7.x86_64 (gdb) bt #0 0x00007fe2df1ef387 in raise () from /lib64/libc.so.6 #1 0x00007fe2df1f0a78 in abort () from /lib64/libc.so.6 #2 0x00007fe2df231ed7 in __libc_message () from /lib64/libc.so.6 #3 0x00007fe2df231fbe in __libc_fatal () from /lib64/libc.so.6 #4 0x00007fe2df2df4c2 in __netlink_assert_response () from /lib64/libc.so.6 #5 0x00007fe2df2dc412 in __netlink_request () from /lib64/libc.so.6 #6 0x00007fe2df2dc5ef in getifaddrs_internal () from /lib64/libc.so.6 #7 0x00007fe2df2dd310 in getifaddrs () from /lib64/libc.so.6 #8 0x000000000047c03c in __interceptor_getifaddrs.part.0 ()

Sistema operativo: Red Hat Enterprise Linux Server versión 7.8 (Maipo)

Versión GLIBC: 2.17

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

El siguiente ejemplo de la página del manual se modificó para incluir su ciclo ocupado con el usleep que se ejecutó durante minutos y bajo valgrind sin arrojar un error; aunque mi servidor no tiene ninguna interfaz de red que falle o se active mientras se ejecuta este ejemplo.

Probé en CentOS 7.9 que tiene glibc-2.17-323.el7_9.x86_64 .

 #include <arpa/inet.h> #include <sys/socket.h> #include <netdb.h> #include <ifaddrs.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { struct ifaddrs *ifaddr, *ifa; int family, s; char host[NI_MAXHOST]; while (1) { if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); exit(EXIT_FAILURE); } /* Walk through linked list, maintaining head pointer so we can free list later */ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; family = ifa->ifa_addr->sa_family; /* Display interface name and family (including symbolic form of the latter for the common families) */ // Commented out } freeifaddrs(ifaddr); usleep(1000); } exit(EXIT_SUCCESS); }

Sin embargo, lo que es interesante: glibc-2.17 de GNU no incluye la __netlink_assert_response , pero glibc-2.31 de GNU sí. Entonces, esto es algo que RedHat parcheó más tarde (puede revisar mis pasos usando):

 SRC=`basename $(rpm -q glibc) .x86_64`.src.rpm wget --no-check-certificate http://vault.centos.org/7.9.2009/updates/Source/SPackages/${SRC} CPIO=`basename ${SRC} .rpm`.cpio rpm2cpio ${SRC} > ${CPIO} mkdir glibc-src && cd glibc-src cpio -ivd < ${CPIO}

Esto muestra que la afirmación que falla en su caso fue agregada por Patch glibc-rh1443872.patch , que dice:

confirmar 2eecc8afd02d8c65cf098cbae4de87f332dc21bd

Autor: ...

Fecha: lun 9 de noviembre 12:48:41 2015 +0100

Terminar el proceso en una respuesta de enlace de red no válida del kernel [BZ #12926]

La entrada de Bugzilla https://sourceware.org/bugzilla/show_bug.cgi?id=12926 brinda detalles sobre la pérdida de la interfaz de NetLink.

Ahora, todo eso no responde a su problema: ¿por qué falla getifaddrs y glibc mata su proceso con la señal SIGABRT ?

Al igual que [@matthieu], supongamos que no estropea su pila y/o el puntero ifaddr en su lógica de monitoreo, esto aún podría ser un error de comunicación entre el kernel y glibc y requeriría una mayor investigación. Como solución alternativa, es posible que capte temporalmente la señal de cancelación como se describe en ¿Cómo manejar la señal SIGABRT?

EDITAR : Por supuesto, si tiene un caso especial para EBADF , debe freeifaddrs(ifaddr) antes de continuar ...

over 4 years ago · Santiago Trujillo Report

0

https://patchwork.ozlabs.org/project/netdev/patch/5638B93F.3090202@redhat.com/

en el enlace dice que el motivo del bloqueo es. "Las llamadas del sistema recvmsg para sockets de enlace de red han sido particularmente propensas a recoger datos no relacionados después de una carrera de descriptores de archivos (donde el descriptor se cierra y se vuelve a abrir al mismo tiempo en un proceso de subprocesos múltiples, como resultado de un problema de gestión del descriptor de archivos en otro lugar). ".

Entonces, creo que no necesita usar un hilo separado o usar algún mecanismo de bloqueo alrededor de las funciones de enlace de red.

Al menos solo confirme que aún falla o no cuando monitorea las interfaces de red en el hilo principal.

over 4 years ago · Santiago Trujillo Report

0

Según man7.org getifaddrs , cualquiera de las operaciones de socket podría ser la causa de EBADF

ERRORES

getifaddrs() puede fallar y establecer errno para cualquiera de los errores especificados para socket(2), bind(2), getsockname(2), recvmsg(2), sendto(2), malloc(3) o realloc(3) .


Sin relación, pero ¿haces freeifaddrs() en alguna parte?

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!