next up previous contents index practicapracticaPP2moodleLHPmoodlepserratacpanmodulospauseperlgoogleetsiiullpcgull
Sig: Práctica: Gestor de Colas Sup: Señales Ant: Controlando warnings en tiempo Err: Si hallas una errata ...

Poniendo límites de tiempo con eval

La función alarm establece un cronómetro. Cuando la cuenta atrás termina el sistema operativo emite una señal ALRM, la cual puede ser interceptada por un manejador de señales. Con un argumento 0 desactiva el cronómetro. Este primer ejemplo pide al usuario un password, controlando si el tiempo de lectura ha excedido un cierto límite:

$ cat time_exceeded.pl
#!/usr/bin/perl -w
use strict;

my $deadline = (shift || 3);
my $time_exceeded = 0;
sub set_time_exceeded { $time_exceeded = 1; }
$SIG{ALRM} = "set_time_exceeded";
print "Teclee su password: ";
alarm($deadline);
my $passwd = <STDIN>;
alarm(0);
print STDERR "Tiempo excedido.\n" if $time_exceeded;

El siguiente ejemplo utiliza eval junto con las señales para establecer un límite al tiempo de espera en una lectura:

> cat eval_alarm.pl
#!/usr/bin/perl -w

use strict;

sub time_out {
  die "Cansados de esperar";
}

my $lim = (shift or 3);
my $buf;

$SIG{ALRM} = "time_out";
eval {
  alarm($lim); # Le indica al SO enviar una señal de ALRM cada $lim s.
  $buf = <>;
  alarm(0); # Cancela la alarma
};
if ($@ =~ /Cansados de esperar/) {
  print "Se acabo el tiempo para la entrada. ¡Adios muy buenas!\n"
} else {
  print $buf;
}
Nótese que si la alarma se activa, $@ contiene algo parecido a "Cansados de esperar at eval_alarm.pl line 6", asi que no se debe usar eq sino una expresión regular.

Ejemplo de ejecución:

> eval_alarm.pl 2
Se acabo el tiempo para la entrada. ¡Adios muy buenas!
> eval_alarm.pl 4
hola
hola

En el siguiente ejemplo utilizamos esta estrategia para saber sobre la conectividad de una máquina. El comando ping nos permite conocer los tiempos de respuesta. La opción -c 1 limita el número de paquetes de prueba a uno. Veamos un ejemplo de uso del comando ping:

$ ping -c 1  etsii
PING etsii (193.145.101.10): 56 data bytes
64 bytes from 193.145.101.10: icmp_seq=0 ttl=63 time=0.7 ms

--- etsii ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.7/0.7/0.7 ms
En este otro ejemplo vemos como es una respuesta negativa:
$ ping -c 1  miranda
PING miranda (193.145.105.176): 56 data bytes

--- miranda ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
El comando ping en ocasiones no termina. En el siguiente ejemplo se comprueba la conectividad de la máquina a través del mismo, limitando el tiempo de espera por ping.
$ cat -n myping.pl
 1  #!/usr/bin/perl -w
 2
 3  use strict;
 4
 5  my @machines = @ARGV;
 6  my ($m, $code) = ("", "");
 7
 8  $SIG{ALRM} = 'kill_it';
 9  for $m (@machines) {
10    eval {
11      alarm(3);
12      $code = `ping -c 1 $m`;
13      alarm(0);
14    };
15    if (defined($@) and ($@ =~ /too long/)) {
16      print "El acceso a $m toma demasiado tiempo.\n";
17      my @ping = `ps -fA`;
18      my @pid = map { /(\d+)\s+$$\b.*\bping -c 1 $m\b/; $1 }  @ping;
19      @pid = grep { defined($_) } @pid;
20      system('ps -fA | grep ping');
21      print "Ejecutamos:\nkill 9, @pid\n" if @pid;
22      kill 9, @pid if @pid;
23      system('ps -fA | grep ping');
24    }
25    else {
26      print "From $m:\ncode = $code\n\n";
27    }
28  }
29
30  sub kill_it { die "too long"; }
$ ./myping.pl miranda # máquin apagada

lhp@nereida:~/Lperl/src$ ./myping.pl miranda # máquina apagada
El acceso a miranda toma demasiado tiempo.
lhp       6058  1899  0 16:16 pts/15   00:00:00 /usr/bin/perl -w ./myping.pl miranda
lhp       6059  6058  0 16:16 pts/15   00:00:00 ping -c 1 miranda
lhp       6061  6058  0 16:16 pts/15   00:00:00 sh -c ps -fA | grep ping
lhp       6063  6061  0 16:16 pts/15   00:00:00 grep ping
Ejecutamos:
kill 9, 6059
lhp       6058  1899  0 16:16 pts/15   00:00:00 /usr/bin/perl -w ./myping.pl miranda
lhp       6059  6058  0 16:16 pts/15   00:00:00 [ping] <defunct>
lhp       6064  6058  0 16:16 pts/15   00:00:00 sh -c ps -fA | grep ping
lhp       6066  6064  0 16:16 pts/15   00:00:00 grep ping
$ ./myping.pl 193.145.105.253 # encendida
From 193.145.105.253:
code = PING 193.145.105.253 (193.145.105.253): 56 data bytes
64 bytes from 193.145.105.253: icmp_seq=0 ttl=64 time=2.0 ms

--- 193.145.105.253 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.0/2.0/2.0 ms


next up previous contents index practicapracticaPP2moodleLHPmoodlepserratacpanmodulospauseperlgoogleetsiiullpcgull
Sig: Práctica: Gestor de Colas Sup: Señales Ant: Controlando warnings en tiempo Err: Si hallas una errata ...
Casiano Rodríguez León
2006-02-21