Después de perseguir el código correspondiente a _gettemp en la implementación de libc de FreeBSD 7, estoy claro con respecto a cómo el contenido del archivo tmp_name
podría ser válido. (Para rastrearlo, puede descargar una copia de PHP 5.2.8 y leer en main/rfc1867.c
- llamadas a la línea 1018 en main/php_open_temporary_file.c
, la función comienza en la línea 227, que hace su trabajo principal en la función que comienza en la línea 97, que, sin embargo, es esencialmente solo un contenedor para mkstemp en su sistema, que se encuentra en el FreeBSD libc implementation en la línea 66 (vinculado), que usa _gettemp (igual que el anterior) para generar el nombre de archivo aleatorio. Sin embargo, the manpage for mkstemp menciona en la sección BUGS que arc4random()
function no reentrante. Es podría ser una posibilidad de que 2 solicitudes simultáneas estén ingresando a la sección del código crítico y devolver el mismo tmp_name
- Sé muy poco acerca de cómo funciona Apache con mod_php o php-cgi para comentar allí (aunque usando FastCGI/php -cgi podría funcionar - No puedo comentar con éxito sobre esto en este momento).
Sin embargo, apuntando a la solución más simple, si no está experimentando el archivo tmp_name
que no es válido, pero colisionando con otros archivos cargados (por ejemplo, si usa la parte de nombre de archivo de tmp_name como su única fuente de exclusividad en el nombre de archivo almacenado), podría enfrentar colisiones debido al birthday paradox. En another question mencionas tener unos 5,000,000 de archivos para mover, y en still another question mencionas recibir 30-40k cargas por día. Esto me parece una situación primordial para una colisión de paradojas de cumpleaños. El mktemp man page menciona que (si usa seis 'X' como lo hace PHP) hay 56,800,235,584 nombres de archivo posibles (62 ** 6, o 62 ** n donde n = número de 'X', etc.). Sin embargo, dado que tiene más de 5 millones de archivos, la probabilidad de una colisión es approximately 100% (otra heurística sugiere que ya habrá experimentado un pedido de 220 colisiones, si ((archivos * (archivos-1))/2)/(62 ** 6) significa cualquier cosa, donde archivos = 5,000,000). Si este es el problema al que se enfrenta (probable, si no agrega más entropía al nombre de archivo cargado generado), puede intentar algo como move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.'))
, con la idea de agregar más aleatoriedad al nombre de archivo aleatorio, evitando colisiones. Una alternativa podría ser agregar dos más 'X' a la línea 134 de main/php_open_temporary_file.c
y volver a compilar.
¿Es su dir de tmp ese el problema o el directorio en el que copia/mueve el archivo? – Greg
Experimento el mismo problema con Freebsd 8 y PHP 5.3. Para reproducir tengo un script de carga muy simple. Para 5 pruebas, es bastante probable que se produzca una colisión. Esto es realmente malo Realmente no tengo ninguna idea por dónde empezar. Este problema también es difícil para Google, como se mencionó anteriormente. –