IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Lecture Asynchrone STDOUT & STDERR


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mars 2007
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 32
    Par défaut Lecture Asynchrone STDOUT & STDERR
    salut,

    Voila la situation, je voudrai lance un processus fils qui execute une commande via system. Le processus pere doit lire les sortie STDERR et STDOUT. Pour cela je cree 2 pipes bien distinct et je redirige les sortie stderr et stdout du fils vers les descripteurs correspondant que le pere lit.

    De facons synchrone pas de pb je lis STDOUT puis STDERR. Seulement je voudrai ne pas etre dependant de l attente sur les descripteurs et avoir donc une lecture asynchrone.

    Pour cela j ai suivie 2 pistes :
    - je file les descripteurs via des threads qui lisent le contenue chacun de leurs cotes. J ai essaye de creer d abord 1 fonction pour lire les flux avant de les lancer dans des threads :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    sub readOutput {                                                                                                                                                 
        my $end_f = 0;                                                                                                                                                
        while( !$end_f ) {                                                                                                                                            
            while( my $l = <$_[0]> ) {                                                                                                                                
                print $l;                                                                                                                                             
            }                                                                                                                                                         
            if( eof(<$_[0]>) ) {                                                                                                                                      
                print "END OF FILE\n";                                                                                                                                
                $end_f = 1;                                                                                                                                           
            }                                                                                                                                                         
        }                                                                                                                                                             
    }
    PB : des la premiere iteration ils sortent de la boucle, de plus si je force la lecture a en faisant tourner la premiere boucle, je me retrouve toujours avec meme chaine de caractere.

    - j ai essaye ensuite d utiliser le flag O_NONBLOCK sur les descripteurs afin de les rendres non bloquant sur lesquels je lis ce qui est renvoye par le fils et j attend le EOF sur les 2 descritpeurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
           my $flags = fcntl(R_OUT, F_GETFL, 0)                                                                                                                      
               or die "Can't get flags for the FILE: $!\n";                                                                                                          
           $flags = fcntl(R_OUT, F_SETFL, $flags | O_NONBLOCK)                                                                                                       
               or die "Can't set flags for the FILE: $!\n";                                                                                                          
     
           $flags = fcntl(R_ERR, F_GETFL, 0)                                                                                                                         
               or die "Can't get flags for the FILE: $!\n";                                                                                                          
           $flags = fcntl(R_ERR, F_SETFL, $flags | O_NONBLOCK)                                                                                                       
               or die "Can't set flags for the FILE: $!\n";                                                                                                          
     
            my $inputEnd =2;                                                                                                                                          
     
            while( $inputEnd != 0) {                                                                                                                                  
     
                print "boucle ";                                                                                                                                      
     
                while( my $err_line = <R_ERR> ) {                                                                                                                     
                    print "R_ERR ". $err_line;                                                                                                                        
                }                                                                                                                                                     
     
                while( my $out_line = <R_OUT> ) {                                                                                                                     
                    print "R_OUT ". $out_line;                                                                                                                        
                }                                                                                                                                                     
     
                if( eof(R_ERR) ) {                                                                                                                                    
                    $inputEnd--;                                                                                                                                      
                    close(R_ERR);                                                                                                                                     
                    print "ERR END \n";                                                                                                                               
                }                                                                                                                                                     
                if( eof(R_OUT) ) {                                                                                                                                    
                    $inputEnd--;                                                                                                                                      
                    close(R_OUT);                                                                                                                                     
                    print "OUT END \n";                                                                                                                               
                }                                                                                                                                                     
            }                                                                                                                                                         
        }

    PB : des la premiere iteration ils sortent aussi de la boucle.


    Donc voila je pense que le probleme vient de la condition de sortie mes boucles, je viens de debuter en perl donc je dois louper quelques choses quelques part, si quelqu'un sait la condition qu'il faut tester afin de savoir quand je peux sortir de la boucle.

    Merci.

  2. #2
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Je suppose que tu utilises open3() ? Il y a des grosses erreurs dans tes scripts, mais je ne les commenterais pas. Ce que tu cherches est disponible avec select(), néanmoins je ne peux que te conseiller d'utiliser plutôt l'un des modules qui permettent une approche de plus haut niveau du problème, par exemple IO::Select ou IO::Multiplex.

    --
    Jedaï

  3. #3
    Membre averti
    Inscrit en
    Mars 2007
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 32
    Par défaut
    non je ne connaissais pas open3, mais c est ce que je cherche, j ai donc utilise open3 avec un select selon un exemple trouve sur le net.

    Merci.

    exemple :
    ------------

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
     local (*READ, *WRITE, *ERROR );                                                                                                                                
        my $pid = open3( \*WRITE, \*READ, \*ERROR, "ls -l" );                                                                                                          
     
        close(WRITE);                                                                                                                                                  
     
        my $sel = IO::Select->new();                                                                                                                                   
        $sel->add(\*ERROR, \*READ);                                                                                                                                    
     
        while(my @ready = $sel->can_read)                                                                                                                              
        {                                                                                                                                                              
            foreach my $handle (@ready) {                                                                                                                              
     
                if (fileno($handle) == fileno(ERROR))                                                                                                                  
                {                                                                                                                                                      
                    my ($count, $data);                                                                                                                                
                    $count = sysread($_, $data, 1024);                                                                                                                 
                    print "ERROR : ". $data;                                                                                                                           
                    exit;                                                                                                                                              
                }                                                                                                                                                      
                else                                                                                                                                                   
                {                                                                                                                                                      
                    my ($count,$data);                                                                                                                                 
     
                    $count = sysread($handle, $data, 1024);                                                                                                            
                    print "READ : " . $data;                                                                                                                           
                }                                                                                                                                                      
                $sel->remove($handle) if eof($handle);                                                                                                                 
     
            }                                                                                                                                                          
                                                                                                                                                                       }                                                                                                                                                              
     
        close(READ);                                                                                                                                                   
        close(ERROR);

  4. #4
    Membre averti
    Inscrit en
    Mars 2007
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 32
    Par défaut
    Petite correction le IO::select n'est pas une bonne solution, des pbs d interblocages apparaissent quand meme:

    If you try to read from the child's stdout writer and their stderr writer, you'll have problems with blocking, which means you'll want to use select() or the IO::Select, which means you'd best use sysread() instead of readline() for normal stuff.

    J'ai donc fait ca avec le flags O_NONBLOCK.

    Ciao

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. stdout.txt stderr.txt ouverture
    Par nightwar dans le forum Eclipse C & C++
    Réponses: 5
    Dernier message: 22/03/2008, 17h48
  2. Filtré sorties stdout et stderr avec open()
    Par Jjeje007 dans le forum Langage
    Réponses: 9
    Dernier message: 09/06/2007, 22h52
  3. [WIN32][TComport] Lecture Asynchrone
    Par Linkin dans le forum Delphi
    Réponses: 5
    Dernier message: 30/03/2007, 10h49
  4. Réponses: 2
    Dernier message: 27/10/2006, 17h07
  5. [Runtime][exec]Récupérer les stdout ET stderr
    Par yveslamand dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 20/05/2005, 13h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo