Newsgroup: it.comp.os.linux.development
Titolo: Perl e socket

Scusate se metto giù una domanda da handicappato dell'informatica, ma ho
un problema stupido e non capisco come venirne fuori...
Di fronte ai vostri insulti ammetto di non essere (e non voler essere...)
un gran programmatore, per cui domando venia delle banalità...
Ho del codice che in un primo abbozzo dovrebbe essere così:
my $sock = IO::Socket::INET -> new (    Listen          =>      5,
                                       LocalAddr       =>      'localhost',
                                       LocalPort       =>      7200,
                                       Proto           =>      'tcp'
                               ) or die "Can't bind $@\n";
my $thissock = $sock -> accept();
while ( 1 ) {
       $thissock -> recv ($dataread, 4096);
       waste_a_lot_of_CPU();
}
close $thissock;
Dentro ci passano dei log provenienti da un syslog-ng, quindi,
afaik, non c'è nulla nel contenuto del socket che mi dica quando
effettuare la close, ecco perchè ciclo indefinitamente.
Il problema è che quando syslog-ng riceve un SIGHUP chiude tutti i
filehandle e li riapre, compreso il socket che punta a 'sta sbobba...
Il risultato è che quel while diviene un loop infinito e non bloccato...
Dovrei poter gestire questo caso in modo da chiudere il filehandle e
tornare in accept()...
Ho ipotizzato un
while ( defined($thissock)) {}
Ma non mi cambia una mazzeruola...
Qualcuno mi indica come va gestito il caso?
Grazie tutti e mi prostro ancora...
-- 
wash the blood from your hands
bury your secrets in the sand
and forget


Sono troppo ignorante di perl, ma vedi se c'e' qualcosa di simile alla
select() in C.
Alessandro.

 select() in C.
Io sono troppo ignorante di tutti e due ;-)
La select per esserci c'è, ma non connetto sul come mi risolve il problema
:-P
Grazie mille, intanto...



Mi apetterei che mettendosi in attesa su un socket disconnesso dia un
qualche segnale di errore (ho dato un occhiata a
http://www.perldoc.com/perl5.8.0/pod/func/select.html
 ma e' veramente molto
sintetica, comunque pinterei su quel "EBITS").
Alessandro.

 Ma non mi cambia una mazzeruola...
Non posso esaminare il tuo codice perche' non ho mai usato i socket con
quell' interfaccia li' (sono un maniaco delle syscall posix), ma
sicuramente
il problema e' dove lo hai individuato tu, cioe' nel test della condizione
anche se probablimente dovresti testare se e' definito $dataread o se e'
di lunghezza 0 bytes.
ti va di provare questo codice?? io lo uso come framework per qualsiasi
server o fakeserver usa e getta che gestisca una sola connessione.
(usa fork() e non select())
---------------
#!/usr/bin/perl
use Socket;
use strict; # e' un pragma per la sicurezza. vedi perldoc -U -m strict
            # mi costringe a dichiarare le variabili com my.
my $err = 0;
my $proto = getprotobyname('tcp');
my $port = 9000;
socket(SOCK, PF_INET, SOCK_STREAM, $proto) or $err = 1;
if ($err) { print "Errore syscall socket\n"; exit 1;}
setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or $err = 1;
if ($err) { print "Errore syscall setsockopt\n"; exit 1;}
bind(SOCK, sockaddr_in($port, INADDR_ANY)) or $err = 1;
if ($err) { print "Errore syscall bind\n"; exit 1;}
listen(SOCK, SOMAXCONN) or $err = 1;
if ($err) { print "Errore syscall listen\n"; exit 1;}
sub REAPER
{
  wait;
  $SIG{CHLD} = \&REAPER;
}
$SIG{CHLD} = \&REAPER; # per eliminare gli zombies.
$SIG{CHLD} = 'IGNORE'; # e' una alternativa a precedente e funziona.
print "Server partito...\n";
while (my $remoteaddr=accept(REMOTE,SOCK))
{
  if (fork())
    {
      close REMOTE;
    }
  else
    {
      close SOCK;
      $SIG{PIPE} = 'IGNORE'; # necessario perche' in perl diversamente che
                             # in C alla chiusura mi arriva un SIGPIPE e
                             # il processo figlio viene ammazzato. ci ho
                             # tribolato un casino.
      my($port,$addr) = sockaddr_in($remoteaddr);
      my $name = gethostbyaddr($addr,AF_INET);
      my $instring;
      # per sicurezza pongo un limite massimo (8096) alla dimensione
      # di $instring
      while (sysread(REMOTE,$instring,8096))
        {
          print $instring; # o waste_cpu();
        }
      exit 0;
    }
}
---------------
ho usato sysread e syswrite perche' non bufferizzate
perldoc -U -f sysread
ritorna il numero di bytes letti o 0 se socket e' stato chiuso. e'
bloccante fino alla ricez. di dati.
Ciao.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 di lunghezza 0 bytes.
In effetti, ho fatto esattamente il test che dici:
esco dal ciclo se la chiamata a recv non torna nulla in $dataread.
E in effetti cosě funziona (con molti ringraziamenti del logrotate di
stanotte ^_^ ).
Grazie per l'ottimo esempio di codice, ne farň buon uso...
Hola!
