en iOS/iPhone: “Demasiados archivos abiertos”: es necesario enumerar los archivos abiertos (como lsof)

5 minutos de lectura

Hemos descubierto que nuestra compleja aplicación para iPhone (ObjC, C++, JavaScript/WebKit) está filtrando descriptores de archivos en circunstancias inusuales.

Necesito saber qué archivos (por ruta de archivo) estamos dejando abiertos.

Quiero algo como el comando BSD “lsof”, que, por supuesto, no está disponible en iOS 4, al menos no para mí. Idealmente una función C u ObjC. O una herramienta, como tiburón o Instrumentos. Solo necesita los archivos para nuestra aplicación en ejecución, no (como con lsof) para todas las aplicaciones/procesos.

Hacemos todo tipo de cosas con archivos, y el código que falla con “Demasiados archivos abiertos” no ha cambiado en mucho tiempo, y dado que las circunstancias son inusuales, esto podría haberse infiltrado hace meses. Por lo tanto, no es necesario que me recuerde que mire el código que abre archivos y me asegure de cerrarlos. Ya lo se. Sería bueno reducirlo con algo lsof-esque. Gracias.

avatar de usuario
Aguas Ricas

#import <sys/types.h>  
#import <fcntl.h>
#import <errno.h>
#import <sys/param.h>

+(void) lsof
{
    int flags;
    int fd;
    char buf[MAXPATHLEN+1] ;
    int n = 1 ;

    for (fd = 0; fd < (int) FD_SETSIZE; fd++) {
        errno = 0;
        flags = fcntl(fd, F_GETFD, 0);
        if (flags == -1 && errno) {
            if (errno != EBADF) {
                return ;
            }
            else
                continue;
        }
        fcntl(fd , F_GETPATH, buf ) ; 
        NSLog( @"File Descriptor %d number %d in use for: %s",fd,n , buf ) ;
        ++n ; 
    }
}

  • Este fragmento finalizó tres días completos de depuración de un error de unity3d. ¡muchas gracias!

    – utahwithak

    18/01/2013 a las 18:25

  • ¿Conoces el límite de archivos abiertos para iOS? ¡Estoy teniendo un problema similar con solo 32 archivos abiertos!

    – Joao Nunes

    20 de marzo de 2013 a las 9:00

  • Perdón por la pregunta estúpida, pero ¿dónde debo colocar este fragmento y cómo puedo usarlo para mi aplicación?

    – lub0v

    25/10/2014 a las 11:55

  • Este fragmento finalizó cuatro días completos de depuración de una aplicación Xamarin.iOS. ¡Muchas gracias!

    – Sanandrea

    10/10/2016 a las 16:28

  • Hice un repositorio en github: github.com/sanandrea/FileCounter.Xamarin

    – Sanandrea

    15 de octubre de 2016 a las 9:09

avatar de usuario
Jaime Iván Cervantes

Para referencia futura, me encontré con un problema similar en un iPhone 11 con iOS 13; Estaba creando demasiados descriptores de archivos (FD) al crear demasiados archivos y sockets. Mi solución fue aumentar los FD en tiempo de ejecución con setrlimit().

Primero obtuve los límites de FD en mi iPhone 11, con el siguiente código:

// This goes somewhere in your code
struct rlimit rlim;

if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
    std::cout << "Soft limit: " << rlim.rlim_cur << std::endl;
    std::cout << "Hard limit: " << rlim.rlim_max << std::endl;
} else {
    std::cout << "Unable to get file descriptor limits" << std::endl;
}

despues de correr getrlimit(), pude confirmar que en iOS 13, el límite suave es 256 FD y el límite estricto es infinito FD. Como estaba creando > 300 FD entre archivos y sockets, mi aplicación fallaba.

En mi caso, no pude disminuir la cantidad de FD, así que decidí aumentar el límite suave de FD en su lugar, con este código:

// This goes somewhere in your code
struct rlimit rlim;

rlim.rlim_cur = NEW_SOFT_LIMIT;
rlim.rlim_max = NEW_HARD_LIMIT;

if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
    std::cout << "Unable to set file descriptor limits" << std::endl;
}

NOTA: Puede encontrar más información en gettrlimit() y setrlimit() aquí y aquí.

avatar de usuario
david gelhar

¿Puede reproducir el problema que se ejecuta en el simulador?

Si es así, entonces podrías usar “lsof”…


actualizar:

Ok, si no puedes usar el simulador, entonces idea #2:

Cuando obtenga el error “demasiados archivos abiertos”, llame a una función que itere a través de todos los descriptores de archivos abiertos y descargue información sobre cada uno (por ejemplo, la longitud y los primeros bytes).

  • Todavía tenemos que reproducir en el simulador. Y no podemos hacer que Instruments haga lo correcto contra el dispositivo. Gracias.

    – Tim James

    3 de noviembre de 2010 a las 22:31


¿No puedes simplemente interceptar todos los archivos abiertos con tu propia función, digamos my_fopeny almacene los descriptores junto con sus nombres para que cuando tenga demasiados archivos abiertos, pueda revisar su lista para ver qué está tomando todos los descriptores.

Si Instruments no funciona bien para sus propósitos, mi próxima recomendación sería ejecutar su aplicación en el simulador y usar fs_usage en la línea de comando para rastrear los descriptores de archivo que está abriendo y cerrando. Algo como esto:

  1. En Terminal, ejecute “sudo fs_usage -f filesys MyAppName”, reemplazando MyAppName con el nombre de su aplicación.
  2. Inicie su aplicación.
  3. Mire el descriptor de archivos que abre y cierra los comandos generados por fs_usage para ver qué archivos está dejando abiertos.

avatar de usuario
Ryan

Instruments.app podría ayudarlo (/Developer/Applications/Instruments.app). Ejecute su aplicación con la herramienta Uso del sistema en Instrumentos y probablemente le mostrará lo que necesita saber. Lo mejor de todo es que se puede usar mientras ejecuta la aplicación en su dispositivo, sin necesidad de hacer jailbreak.

avatar de usuario
Seguro en sí mismo

Le sugiero que ejecute su aplicación en un iPhone con jailbreak y use Backgrounder y MobileTerminal para ver los archivos abiertos actualmente.

Puede obtener un binario de iPhone de lsof aquí: http://modmyi.com/cydia/package.php?id=6945

  • Gracias. Tenemos un último dispositivo con jailbreak aquí. Pero él y su jailbreak son más antiguos y no toleraban la instalación de lsof.

    – Tim James

    4 de noviembre de 2010 a las 19:06

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad