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

C Discussion :

exec bloquant avec php


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut exec bloquant avec php
    Bonjour à tous,

    j'utilise dans mon code C l'instruction execl pour l'exécution d'un script php.

    Je ne comprend pas pourquoi mais cette instruction "bloque". En effet, mon script C arrive à cette ligne et reste figé sans rentrer dans mon script php :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    printf("test1");
    execl("/usr/bin/php","php","mail.php",NULL);
    printf("test2");
    Le résultat affiche bien test1 puis attend. Dans mon script php j'ai mit un "echo "je passe ici"" au tout début et apparement il ne reste même pas dans mon script.

    J'ai aussi essayé aec execlp("php","mail.php",NULL) et même résultat.

    Je me trouve bien, lors de l'exécution, dans le même dossier que mail.php.

    Merci d'avance

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Bonjour,

    La famille des fonctions exec() remplace le processus courant par le programme que tu veux lancer. Aucune chance, donc, de voir apparaître « test2 ». Tape Entrée pour vérifier si ton script est réellement bloqué ou pas.

    Le résultat affiche bien test1 puis attend. Dans mon script php j'ai mit un "echo "je passe ici"" au tout début et apparement il ne reste même pas dans mon script.
    Il ne reste pas ou il ne rentre pas ? Ton message « je passe ici » s'affiche ou pas ?

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Merci pour ton aide.

    Il ne rentre pas...désolé faute de frappe.
    Mon message "je passe ici" ne s'affiche pas.

    J'ai tapé Entrée et le prompt dans la console descend. Donc apparemment le script n'est pas bloqué mais continue à tourner "dans le vide".

    EDIT: j'ai effectué l'exécution du script en console et le script se lance parfaitement donc le problème vient surement de ma comande execl mais je ne comprends toujours pas pourquoi

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Essaie déjà de mettre des retours à la ligne dans tous tes print, que ce soit dans le programme C comme dans le script PHP. Sinon, le message risque de rester dans le buffer et de ne jamais s'afficher. Ce serait dommage.

    Qu'entends-tu par « le prompt dans la console descend » ? Si c'est le curseur qui saute une ligne sans qu'il ne se passe rien, tu es toujours bloqué. Par contre, si c'est l'invite de saisie (le prompt) style « /home/toto $ » qui se réaffiche une ligne plus bas, ça veut dire que le programme a rendu la main depuis longtemps (ou s'est émancipé).

    Enfin, je viens de faire le test chez moi et ça fonctionne.

    Tu travailles sous quel système d'exploitation ?

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    J'ai ajouté des retours à la ligne à tous mes prints et rien ne change.

    Oui le curseur saute une ligne sans que rien ne se passe.
    Le prompt « /home/toto $ » ne se ré-affiche pas. Je suis obligé de faire un Ctrl+c.

    Je suis sous Ubuntu 9.10

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Alors, il faut nous donner le code entier : celui de ton programme C (toute la fonction), et le code PHP.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Voici le code C :

    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
     
    //Fonction de terminaison de processus pour l'envoie d'email
    void envoie_mail(int code, struct Email *mail)
    {
    	chdir("/var/www/Test/librairies/PEAR");
     
            printf("test1");
     
    	execl("/usr/bin/php","php","mail.php",mail->adresse,NULL);
    }
     
     
    int main()
    {
           on_exit( (void(*)(int , void *))envoie_mail ,&email);
     
           setpgid(0,0);
     
           ... // [essentiellement lecture dans fichiers]
    }
    Dans ce code-ci j'arrive à atteindre le printf.

    Pour le code php...

    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
     
    <?php
    require_once "Mail.php";
    include('Mail/mime.php');
     
    echo "je passe ici\n";
     
    //quelques initialisations pour l'email
     
    //----- Construction MIME-----//
    $crlf = "\n";
    $mime = new Mail_mime($crlf);
     
    $mime->setTXTBody($body);
    $body = $mime->setHTMLBody($html);
    $headers = $mime->headers($headers);
     
    $body = $mime->get();
     
    //Envoie de l'email
    $mail = $smtp->send($to, $headers, $body);
     
    if (PEAR::isError($mail)) 
    {
      echo("<p>" . $mail->getMessage() . "</p>");
    } 
    else 
    {
      echo("Message successfully sent! ");
    }
    ?>

    Merci pour l'aide

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Bonjour,

    je viens de trouver la ligne de code qui pose problème.

    Dans mon main je change l'appartenance du groupe de mon processus avec
    setpgid(0,0).

    Je ne comprends pas pourquoi, quand j'enleve cette commande, execl s'exécute et quand je la mets, execl ne vuet pas s'exécuter.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Pour faire avancer la discussion...

    Avec execl, si j'ai bien compris le processus courant est remplacé par celui exécuté c'est bien?

    Donc il prend la valeur du pid et gpid non?

    Bizarre qu'en changeant le groupe avant l'execl ne fonctionne plus.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Auriez-vous une solution pour pouvoir changer le groupe du processus courant sans bloquer l'execl?

    En fait je change le groupe du processus courant car dans mon main, j'utilise également popen et je voudrais pouvoir le tuer mais comme on ne peut pas récuperer le pid du processus lancé par popen, la seule solution était de tuer le groupe de processus d'où le besoin de changer le pid du groupe.

  11. #11
    Membre émérite Avatar de sloshy
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2005
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Janvier 2005
    Messages : 728
    Par défaut
    Bonjour,
    Un fork() ou un system() ne permettrait pas de garder la main dans le process courrant et ainsi eviter tout problème?

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Est-il possible avec un system de récuperer le pid du processus créé et de ne tuer que lui?

    Apparement non : ici ils expliquent qu'il est préférable d'implementer son propre system...

    J'utilisais popen pour la récupération de résultat mais je ne sais pas si j'ai effectué le bon choix.

    Ce que je veux c'est que tout les résultats de la commande exécutée soit automatiquement récupérés dans un fichier... un peu dans le même style que "> result.txt" à la fin d'une commande sous linux.

    Est-il plus approprié d'utiliser system pour ce genre de chose en ajoutant "> result.txt" à la fin de la commande?



    Merci

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Pour être honnête, on ne sait toujours pas réellement à quel endroit ton blocage se produit, et le code que tu nous as montré est plein de particularités qui peuvent influer sur le déroulement d'un programme. À commencer par on_exit(), qui est une fonction dépréciée, et qui ne devrait compiler qu'en présence des bonnes macros.

    Ensuite, setpgid(0,0) aligne le PGID du processus sur son propre PID, ce qui est déjà le cas si il est lancé seul. Sauf cas particuliers à ta situation, le PGID ne diffère que si ta commande fait partie d'un pipeline. Changer de PGID peut rendre ton programme bloquant − dans ce cas seulement − si le Shell donne la parole au job en premier plan. Exécuté seul, il ne devrait rien se passer et les extraits que tu nous as donnés, compilés chez moi, fonctionnent sans blocage.

    À mon avis, si on regardait le code caché derrière tes commentaires, on trouverait encore pas mal de surprises.

    Essaie de lancer ton programme à travers strace pour voir quel est le dernier appel système effectué.

    Est-il plus approprié d'utiliser system pour ce genre de chose en ajoutant "> result.txt" à la fin de la commande?
    D'une manière générale, system() sert justement à laisser le système travailler pour nous, et à lancer des commandes de façon simple mais temporaire. Il ne faut pas prendre l'habitude de l'utiliser et encore moins de s'appuyer dessus. Et, en tout état de cause, il ne faut surtout pas se rabattre dessus avant d'avoir d'être sûr d'avoir compris ce qui te bloquait jusque là.

    Si tu veux rediriger la sortie standard vers un fichier sans passer par le Shell, le plus propre est de commencer par ouvrir le fichier en écriture avec open(), vérifier que l'opération a réussi, retrouver le descripteur de stdout avec fileno() (en pratique, toujours « 1 »), dupliquer le descripteur du fichier ouvert vers celui de stdout avec dup2() (l'ancienne sortie sera automatiquement refermée en cas de succès), refermer le descripteur original retourné par open() avec close(), puis lancer execl().

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Avant tout merci pour toutes ces explications.

    Je ne connaissais pas strace. J'ai essayé et j'obtiens ceci comme dernière ligne (donc lorsque ça bloque) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    close(4)                                = -1 EBADF (Bad file descriptor)
    accept(3, 0x7fffd54abf00, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) @ 0 (0) ---
    accept(3
    Ensuite quand j'effectue le contrôle+C

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    close(4)                                = -1 EBADF (Bad file descriptor)
    accept(3, 0x7fffd54abf00, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) @ 0 (0) ---
    accept(3, 0x7fffd54abf00, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGINT (Interrupt) @ 0 (0) ---
    +++ killed by SIGINT +++
    J'ai un peu de mal à interpréter ces résultats mais l'erreur viendrait-elle au niveau de "bad file descriptor"?

    Le accept(3, ) correspond à la sortie d'erreur?


    Je vais essayer d'expliquer ce que j'aimerai réaliser ça sera peut être mieux.
    Je veux pouvoir exécuter une commande que je reçois via une socket. J'aimerai récupérer l'exécution de cette commande dans un fichier "result.txt" afin de l'envoyer ensuite par email (via un script php).

    Je me dis que si j'utilise exec, alors je ne reviendrais plus dans ma fonction et donc je ne pourrais pas envoyer l'email.
    C'est pourquoi il me restait comme choix system ou popen.

    Pour le choix de on_exit, j'avais choisi celà pour être certain qu'on exécute le script d'envoie d'email à chaque fois. Maintenant je me dit qu'il serait peut-être mieux de bien gérer les erreurs à chaque niveau (j'entends surtout au niveau de l'exécution de la commande afin de savoir si elle s'est bien déroulée ou pas) et de mettre comme dernière instruction de ma fonction principale, l'envoie de l'email...

    A mon avis ça serait plus "propre" comme la fonction on_exit est dépréciée.


    Encore merci pour l'aide aportée.

  15. #15
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Citation Envoyé par dvp_zero Voir le message
    Avant tout merci pour toutes ces explications.

    Je ne connaissais pas strace. J'ai essayé et j'obtiens ceci comme dernière ligne (donc lorsque ça bloque) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    close(4)                                = -1 EBADF (Bad file descriptor)
    accept(3, 0x7fffd54abf00, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) @ 0 (0) ---
    accept(3
    Ensuite quand j'effectue le contrôle+C

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    close(4)                                = -1 EBADF (Bad file descriptor)
    accept(3, 0x7fffd54abf00, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) @ 0 (0) ---
    accept(3, 0x7fffd54abf00, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGINT (Interrupt) @ 0 (0) ---
    +++ killed by SIGINT +++
    Il nous faudrait les lignes au-dessus aussi. Essaie de les rediriger vers un fichier, et de vérifier ensuite si tu y aperçois un appel à « mail.php » quelque part. Je suis persuadé que c'est ton script PHP qui pose problème et pas le code C.

    J'ai un peu de mal à interpréter ces résultats mais l'erreur viendrait-elle au niveau de "bad file descriptor"?

    Le accept(3, ) correspond à la sortie d'erreur?
    Non. accept() sert à accepter une connexion entrante sur un socket dont on est à l'écoute. Donc, soit c'est un socket Unix, soit c'est directement une connexion TCP, mais c'est peu problable. Les flux standards, eux, courent de 0 à 2. « 3 » est le premier descripteur ouvert (ou hérité) par le programme.

    Je vais essayer d'expliquer ce que j'aimerai réaliser ça sera peut être mieux. Je veux pouvoir exécuter une commande que je reçois via une socket. J'aimerai récupérer l'exécution de cette commande dans un fichier "result.txt" afin de l'envoyer ensuite par email (via un script php).

    Je me dis que si j'utilise exec, alors je ne reviendrais plus dans ma fonction et donc je ne pourrais pas envoyer l'email.
    C'est pourquoi il me restait comme choix system ou popen.
    Ou encore fork() suivi d'un exec() mais cela revient au même.

    Déposer le résultat de la commande dans un fichier pour l'envoyer ensuite n'est pas la meilleure idée qui soit. Il vaut mieux directement tuber la commande vers le programme d'envoi de mail.

    Pour le choix de on_exit, j'avais choisi celà pour être certain qu'on exécute le script d'envoie d'email à chaque fois. Maintenant je me dit qu'il serait peut-être mieux de bien gérer les erreurs à chaque niveau (j'entends surtout au niveau de l'exécution de la commande afin de savoir si elle s'est bien déroulée ou pas) et de mettre comme dernière instruction de ma fonction principale, l'envoie de l'email...

    A mon avis ça serait plus "propre" comme la fonction on_exit est dépréciée.
    En fait, c'est surtout atexit() qu'il faut utiliser.

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Voici l'entièreté du trace :

    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
    38
    39
    40
    41
    42
    execve("./Serveur", ["./Serveur"], [/* 36 vars */]) = 0
    brk(0)                                  = 0x1284000
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f067193a000
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0671938000
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    fstat(3, {st_mode=S_IFREG|0644, st_size=109697, ...}) = 0
    mmap(NULL, 109697, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f067191d000
    close(3)                                = 0
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    open("/lib/libc.so.6", O_RDONLY)        = 3
    read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\353\1\0\0\0\0\0"..., 832) = 832
    fstat(3, {st_mode=S_IFREG|0755, st_size=1490312, ...}) = 0
    mmap(NULL, 3598344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f06713ae000
    mprotect(0x7f0671514000, 2093056, PROT_NONE) = 0
    mmap(0x7f0671713000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x165000) = 0x7f0671713000
    mmap(0x7f0671718000, 18440, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0671718000
    close(3)                                = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f067191c000
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f067191b000
    arch_prctl(ARCH_SET_FS, 0x7f067191b6f0) = 0
    mprotect(0x7f0671713000, 16384, PROT_READ) = 0
    mprotect(0x601000, 4096, PROT_READ)     = 0
    mprotect(0x7f067193b000, 4096, PROT_READ) = 0
    munmap(0x7f067191d000, 109697)          = 0
    socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
    bind(3, {sa_family=AF_INET, sin_port=htons(5000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
    listen(3, 128)                          = 0
    accept(3, {sa_family=AF_INET, sin_port=htons(36143), sin_addr=inet_addr("127.0.0.1")}, [16]) = 4
    clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f067191b7c0) = 3987
    close(4)                                = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0671937000
    write(1, "\n", 1)                       = 1
    write(1, "----------------------\n", 23) = 23
    close(4)                                = -1 EBADF (Bad file descriptor)
    accept(3, 0x7fffa3226940, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGCHLD (Child exited) @ 0 (0) ---
    accept(3, 0x7fffa3226940, [17179869200]) = ? ERESTARTSYS (To be restarted)
    --- SIGINT (Interrupt) @ 0 (0) ---
    +++ killed by SIGINT +++

    J'ai également effectué un strace en enlevant setpgid(0,0) (donc lorsque l'appel au script mail.php fonctionne) et je ne trouve pas l'appel dans le trace. Aucune ligne ne référence mail.php.


    Pour on_exit, il avait l'avantage par rapport à atexit de prendre des arguments (je pouvais donc entre autre spécifier le dossier stockant le résultat de l'exécution car il est variable).

    J'avais pensé créer un tube entre Php et C mais j'avoue que je ne voyais pas comment faire. La seule façon que j'ai trouvé fut de passer par une socket mais comme j'en utilise déjà une, je voulais pas avoir une socket dans une socket.

    Maintenant, avec les fonctions que tu m'as cité ci-avant (dup2,etc), il est peut-être possible de déplacer la sortie standard du résultat de l'exécution vers l'entrée standard de l'exécution du script d'email. Je ne suis vraiment pas habitué à "jouer" avec les sorties.

  17. #17
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Est-ce que c'est possible d'avoir tout le code C ?

    J'ai également effectué un strace en enlevant setpgid(0,0) (donc lorsque l'appel au script mail.php fonctionne) et je ne trouve pas l'appel dans le trace. Aucune ligne ne référence mail.php.
    Encore une fois, cela ne s'explique que si tu lances ta commande dans un pipeline Shell. Tu peux nous montrer également la ligne de commande que tu tapes pour lancer ton application ?

    La seule façon que j'ai trouvé fut de passer par une socket mais comme j'en utilise déjà une, je voulais pas avoir une socket dans une socket.
    Un socket dans un socket ? Ça ne signifie rien. Les sockets sont, vus du code, des descripteurs semblables à ceux des fichiers et complètement indépendants entre eux. Je ne vois pas ce que tu entends par un socket à l'intérieur d'un autre…

    Maintenant, avec les fonctions que tu m'as cité ci-avant (dup2,etc), il est peut-être possible de déplacer la sortie standard du résultat de l'exécution vers l'entrée standard de l'exécution du script d'email. Je ne suis vraiment pas habitué à "jouer" avec les sorties.
    C'est en substance ce que fais le Shell quand tu pipes.

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    110
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 110
    Par défaut
    Voici l'entièreté du code C :

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    int socket_id;
     
    //Fonction de terminaison de processus pour l'envoie d'email
    void envoie_mail(int code, struct Email *mail)
    {
    	int pid = getpid();
    	char pid_val[24]={0x0};
    	sprintf(pid_val,"%d",pid);
     
    	printf("Code de terminaison : %d\n",code);
    	(void)code;
     
    	printf("L'email est envoye \n");
     
    	chdir("/var/www/Test/librairies/PEAR")
     
    	execl("/usr/bin/php","php","mail.php",mail->dir_result,pid_val,mail->mail,NULL);//,mail->dir_result,pid_val,NULL);
    }
     
     
    //Routine pour l'exécution de programme
    void traitement(int socket)
    {
    	char buffer[1000];
    	char login[100];
    	char dirName[100];
    	char fileName[] = "result.txt";
    	char pid_String[4];
    	char dir[] = "/home/";	
    	int pid = getpid();
     
    	Email email;
    	Execution execution;
    	FILE* flux = NULL;
    	FILE* fichierJoin = NULL;
    	email.pid = pid;
     
    	sprintf(pid_String,"%d",pid);
     
    	//  Fonction de terminaison de processus 
    	on_exit( (void(*)(int , void *))envoie_mail ,&email);
     
     
    	//   Réception de la chaine 
    	recv(socket,buffer, sizeof(execution.path), 0);
     
    	//    Envoie du PID	           
    	send(socket,pid_String,sizeof(char)*4,0);
     
    	close(socket);		   	
     
    	strcpy(execution.path,buffer);
    	strcpy(execution.email,buffer + strlen(execution.path) +1);
    	strcpy(login, buffer + strlen(execution.path) +1 + strlen(execution.email) +1);
     
    	strcat(dir,login);
     
    	chdir(dir);
    	sprintf(dirName,"tmp%d",pid);
    	strcat(dir,"/");
    	strcat(dir,dirName);
     
    	strcpy(email.dir_result,dir);
    	strcpy(email.mail,execution.email);
    	mkdir(dirName,00700);//creation du repertoir temporair
     
    	//Changement du repertoir de travail 
    	chdir(dirName);
     
     
       	//Execution du programmes :  	
       	fichierJoin = fopen("result.txt", "a+"); 
     
    	flux = popen (execution.path, "r");
     
    	while(fgets (email.result, 1000, flux)!= NULL) 
    		fprintf (fichierJoin,"%s", email.result);
     
    	fclose(fichierJoin);
    	pclose (flux);
     
    	exit(0);	
    }
     
     
    int main()
    {	
    	int s=0;
     
            struct sockaddr_in adresse;
    	adresse.sin_family = AF_INET;
    	adresse.sin_port = htons(5000);
    	adresse.sin_addr.s_addr=inet_addr("127.0.0.1");
     
    	int addr_size = sizeof(adresse);
     
    	socket_id = socket(AF_INET,SOCK_STREAM,0); 
    	bind(socket_id, (struct sockaddr*) &adresse, addr_size);	
    	listen(socket_id, SOMAXCONN);	
     
     
    	//Ecoute de la socket
    	//--------------------
    	while(1)
    	{
    		s = accept(socket_id, (struct  sockaddr*)&adresse, &addr_size);
     
    		int p=fork();
    		if(p>0)
    		{
    			close(s);	
    		}	
    		else
    		{
    			setpgid(0,0);
    			nice(15); 
    			traitement(s);
    		}
    		close(s);                
     
    	}	
    }
    Pour lancer ma commande :

    et avec strace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strace -o trace.txt ./Serveur

    Par socket dans socket, j'entendais par là de réouvrir un(e?) socket dans le traitement de ma première socket ouverte.

Discussions similaires

  1. sudo chown avec PHP exec ne fontionne pas
    Par mqxxou dans le forum Applications et environnements graphiques
    Réponses: 10
    Dernier message: 17/11/2012, 19h26
  2. Travailler avec PHP / Apache / MySQL
    Par R3iTt0R dans le forum Linux
    Réponses: 22
    Dernier message: 24/06/2004, 11h03
  3. [débutant] choix de postgre avec php / migration
    Par bilbon.S dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 23/03/2004, 14h05
  4. Création d'utilisateur sous PostgreSQL 7.3.2 avec PHP
    Par duongkhang dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 06/06/2003, 13h10

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