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

Programmation et administration système Perl Discussion :

process defunct avec fork et exec


Sujet :

Programmation et administration système Perl

  1. #1
    Nouveau membre du Club
    Profil pro
    nabbo
    Inscrit en
    Décembre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : nabbo

    Informations forums :
    Inscription : Décembre 2005
    Messages : 35
    Points : 25
    Points
    25
    Par défaut process defunct avec fork et exec
    Hello


    J'ai un soucis avec un script perl que j'essaie de faire, qui fait un fork de lui-même, pour calculer son temps d'execution (en gros, l'idée étant de faire une action si le temps est supérieur ou inférieur à un temps défini, mais sans attendre la fin de l'execution si c'est plus long que prévu)


    Le code :
    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
     
     
        #!/usr/bin/perl
        $cmd = "sleep 20 ";
        my $pid;
        defined($pid = fork()) or die "unable to fork: $!\n";
        if ($pid == 0) { #parent
          exec($cmd);
          die ;
        }
        else { #child
        $time=0;
        while(1) {
         $rc = system("ps -p".$pid." 2>&1 >/dev/null" );
         if($rc==0){
          print "pid $pid still running after $time seconds\n";
         }
         else{
          print "pid $pid running after $time seconds\n";
          exit;
         }
         $time+=5;
         sleep 5;
        }
        }

    quand je lance, tout va bien jusqu'à 20 secondes, puis le process sleep passe en defunct, et le process parent attend dans le vide.


    pour l'instant, c'est sur du linux, mais il faudrait que ca marche également sous windows... si possible


    Idéalement, quand le script parent "sleep 20" se finit, j'aimerais obtenir son return code...


    Une idée ?


    merci !

  2. #2
    Membre régulier
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 71
    Points : 87
    Points
    87
    Par défaut
    salut,

    je me trompe peut-être mais tu fais une erreur de logique.

    ton fork te permet de lancer un programme ou une commande et permettre a ton script de continuer sans ne plus s'occuper de ce qui est dans le fork.

    par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if (defined($menu_pid = fork)) { 
    	if ($menu_pid == 0) { 
    		exec "cd blabla && perl blabla.pl"; 
    	}
    }

    la dedans, ca va faire un cd puis executer un autre script Perl MAIS EN AUCUN CAS REVENIR EN ARRIERE A LA FIN DE blabla.pl
    donc, tu devrais au lieu de ton :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        $cmd = "sleep 20 ";
        my $pid;
        defined($pid = fork()) or die "unable to fork: $!\n";
    if ($pid == 0) { #parent
          exec($cmd);
          die ;
        }

    avoir un truc genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        my $pid;
        defined($pid = fork()) or die "unable to fork: $!\n";
    if ($pid == 0) { #parent
          exec('sleep 20 && pid=$(ps -C "perl setup.pl" -o pid=) && kill $pid');
        }
    remplace bien entendu perl setup.pl par le tien mais laisse bien les "

    et la, au bout de 20 secondes, fini ou pas fini, ton script principal sera tué par le kill.

    par contre, n'ayant pas de windows, je n'ai pas pu le tester sous windows.

    cordialement

    ours

  3. #3
    Nouveau membre du Club
    Profil pro
    nabbo
    Inscrit en
    Décembre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : nabbo

    Informations forums :
    Inscription : Décembre 2005
    Messages : 35
    Points : 25
    Points
    25
    Par défaut
    Hello, et merci pour la réponse.

    En fait, je ne veux pas killer le process qui tourne, je veux simplement faire une action quand le process tourne trop longtemps (tout en laissant le process tourner)

    De plus, je ne suis pas sûr que récupérer le PID via la commande ps -C soit efficace, parce que si jamais j'ai plusieurs process avec le même nom, comment le script va-t-il réagir ?

  4. #4
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    bonjour,

    à priori ce que tu cherches à faire c'est un timeout sur un traitement qui lui est potentiellement bloquant j'imagine (comme une operation sur les sockets par exemple), ce qui correspond à la fonction alarm qui permet de lever un signal SIGALRM au bout d'un nombre de secondes donné, le principe est donc d'indiquer au programme qu'à la réception dudit signal on veut qu'il exécute notre fonction

    le code d'exemple tiré de la doc est très parlant :

    Code perl : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    eval {
       local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
       alarm $timeout;
       $nread = sysread SOCKET, $buffer, $size;
       alarm 0;
    };
    if ($@) {
       die unless $@ eq "alarm\n"; # propagate unexpected errors
       # timed out
    }
    else {
       # didn't
    }

  5. #5
    Nouveau membre du Club
    Profil pro
    nabbo
    Inscrit en
    Décembre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : nabbo

    Informations forums :
    Inscription : Décembre 2005
    Messages : 35
    Points : 25
    Points
    25
    Par défaut
    Bon. j'ai obtenu quelque chose de pas très propre... mais qui marche à peu près :
    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
     
    my $pid;
    defined($pid = fork()) or die "unable to fork: $!\n";
     
    if ($pid == 0) { #parent : launch the process
    	$cmd = "sleep 20";
     
    	$rc = system($cmd);
    	$rc = $rc >>= 8;
     
    	if ($rc > 127) {$rc -= 256;} 
     
    	print "rc=$rc\n";
     
    	exit;
    }
    else { #child : monitoring
    	$time=0;
    	$sleepTime = 1;
    	while(1) {
    		$out = `ps -p$pid | grep $pid | grep -v defunct`;
     
    		if($out!="") {
    			print "pid $pid still running after $time seconds\n";
    		}
    		else {
    			print "pid $pid not running after $time seconds\n";
    			exit;
    		}
     
    		$time+=$sleepTime;
    		sleep $sleepTime;
    	}
    }
    Le problème est que le process appelé part quand même en defunct, mais j'ai modifié l'utilisation du ps pour l'ignorer. S'il part en defunct, alors je considère qu'il n'est plus là, et mon script sort. Quand mon script sort, le process "defunct" lui-même est arrêté.

    C'est pas très propre, mais ca marche.

    Est ce qu'il y a moyen de faire plus propre ?

  6. #6
    Nouveau membre du Club
    Profil pro
    nabbo
    Inscrit en
    Décembre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : nabbo

    Informations forums :
    Inscription : Décembre 2005
    Messages : 35
    Points : 25
    Points
    25
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    bonjour,

    à priori ce que tu cherches à faire c'est un timeout sur un traitement qui lui est potentiellement bloquant j'imagine (comme une operation sur les sockets par exemple), ce qui correspond à la fonction alarm qui permet de lever un signal SIGALRM au bout d'un nombre de secondes donné, le principe est donc d'indiquer au programme qu'à la réception dudit signal on veut qu'il exécute notre fonction

    le code d'exemple tiré de la doc est très parlant :

    Code perl : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    eval {
       local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
       alarm $timeout;
       $nread = sysread SOCKET, $buffer, $size;
       alarm 0;
    };
    if ($@) {
       die unless $@ eq "alarm\n"; # propagate unexpected errors
       # timed out
    }
    else {
       # didn't
    }
    Je ne veux pas arrêter le process au bout du timeout, mais seulement faire une action (afficher un message, pour l'exemple)

    J'ai essayé ton script en commentant le "die unless", mais ca arrête quand même le process au bout de timeout...

Discussions similaires

  1. cleaning process fils avec waitpid() fork exec pselect
    Par thorgal99 dans le forum Réseau
    Réponses: 2
    Dernier message: 19/08/2014, 11h59
  2. Connaitre PID d'un process lancé avec exec()
    Par hugo123 dans le forum Langage
    Réponses: 4
    Dernier message: 02/06/2006, 14h28
  3. Process defunct bizarre avec Mon sur mandriva
    Par spynux dans le forum Administration système
    Réponses: 4
    Dernier message: 22/12/2005, 09h32
  4. Erreur avec fork
    Par strach dans le forum Programmation et administration système
    Réponses: 6
    Dernier message: 13/08/2005, 11h35
  5. [Swing] execution avec Runtime.getRuntime().exec
    Par benssj5 dans le forum AWT/Swing
    Réponses: 9
    Dernier message: 25/08/2004, 14h54

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