Bueno, la forma moderna de abrir un archivo es así:
open my $HANDLE, '>>', 'archivo.log';Así que ya ves que el gestor de archivo es una variable. Y por lo tanto, la puedes compartir entre los distintos hilos.
Ahora bien... es muy posible que varios hilos intenten escribir a la vez. Mientras un hilo está escribiendo algo, en ese momento puede entrar en la CPU el contexto de otro hilo, que escribirá su correspondiente salida. Luego regresa al primero hilo, que escribirá el resto. Así que la salida queda mezclada.
Habría que usar un sistema de bloqueo en el acceso, o un sistema parecido a lo que usan programas como Apache, que permiten que varios hilos accedan a los mismos registros (la verdad, no sé cómo lo hacen, creo que tiene que ver con tuberías -
pipes-, pero no lo he mirado).
Si abres el mismo archivo pero con descriptores diferentes, cada descriptor guardará un puntero de posicionamiento de escritura diferente, por lo que la salida de un hilo quedará sobrescrito por la salida de los demás.
El asunto es complejo, sin duda. La clave está en lo siguiente: en los sistemas UNIX es casi imposible realizar una operación de escritura en un archivo, de forma simultánea, sin corromper el propio archivo.
Hay varias opciones. Por ejemplo: cuando un hilo quiere escribir en el registro, primero lo bloquea (lock()), luego hace un seek() para posicionarse al final del registro, escribe la salida, y termina desbloqueando el acceso. Ejemplo:
Using perl Syntax Highlighting
sub proceso {
lock(\*LOG); # bloquear
print LOG "lo-que-sea..."; # pintar
unlock(\*LOG); # desbloquear
}
use Fcntl qw(:flock SEEK_END);
sub lock {
my ($fh) = @_; # recibimos el descriptor de archivo
flock($fh, LOCK_EX) or die $!; # solicitamos el bloqueo, y de forma esclusiva
seek($fh, 0, SEEK_END) or die $!; # nos colocamos al final del archivo
}
sub unlock {
my ($fh) = @_;
flock($fh, LOCK_UN) or die $!; # desbloqueamos el acceso
}
Coloreado en 0.004 segundos, usando
GeSHi 1.0.8.4
Hay soluciones más elaboradas, como la de que ir creando espacio (un relleno de ceros) justo antes de escribir la propia línea, en el registro.
En este hilo de blogs.perl.org se comenta el mismo problema:
Suprisingly hard task of writing logs. Y también se comentan diversas soluciones.