Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

system(3) : Analyse code d'erreur

3 réponses
Avatar
fponroy
Bonjour,

J'ai un petit souci d'analyse des codes d'erreur de l'appel system(3).
Pour simplifier, la partie de mon code int=E9ressante (et incrimin=E9e !)
effectue les op=E9rations suivantes :

- Cr=E9ation d'un fichier temporaire avec mkstemp(3) ;
- Ajout de commandes au fichier avec plusieurs write(2) successifs.
Chaque ligne de commande ajout=E9e au fichier poss=E8de la syntaxe
suivante : commande shell || exit 1 ;
- Synchronisation des donn=E9es du fichier sur disque avec fsync(2) ;
- Fermeture du fichier avec close(2) ;
- Ajout des droits d'ex=E9cution au fichier avec un chmod(1) appel=E9 via
system(3) ;
- Execution du fichier avec system(3).

C'est lors de ce dernier appel que j'obtiens les codes d'erreur
suivants :

- Valeur de retour de system(3) : 256 ;
- Errno : 2 (No such file or directory) ;
- WEXITSTATUS(256) : 1.

Mes questions sont les suivantes :

- Comment interpr=E9ter ces codes d'erreur ?
- A quoi correspond le '1' du WEXITSTATUS() ? Est-ce un '1' renvoy=E9
par le fichier temporaire sur =E9chec d'ex=E9cution d'une commande shell
?
- L'erreur 2 d'errno signifie-t-elle que mon fichier temporaire
n'existe finalement pas du tout ?

Pour information, le code a =E9t=E9 compil=E9 avec gcc sans aucune
optimisation, et tourne sur une RedHat Entreprise 3.0 Update 6 (Noyau
2=2E4.21-37).

Merci pour vos =E9claircissements, et pardonnez-moi si je n'ai pas
post=E9 sur le bon groupe !

Florian

3 réponses

Avatar
Eric Levenez
Le 4/01/07 16:01, dans
,
«  » a écrit :

Premièrement tout ce qui suit n'est pas du C standard et devrait être posté
sur un NG dédié à ta plateforme.

J'ai un petit souci d'analyse des codes d'erreur de l'appel system(3).
Pour simplifier, la partie de mon code intéressante (et incriminée !)
effectue les opérations suivantes :


Si on tient à gérer finement le code de retour de system, alors on n'utilise
pas system mais fork/exec.

- Création d'un fichier temporaire avec mkstemp(3) ;
- Ajout de commandes au fichier avec plusieurs write(2) successifs.


Vu que tu écris du texte par ligne, le mieux aurait dû être d'utilise
fopen/fprintf/fclose...

Chaque ligne de commande ajoutée au fichier possède la syntaxe
suivante : commande shell || exit 1 ;


Bizarre comme commande : si ton shell part en erreur (ne retourne pas 0),
alors tu forces le code non nul à 1. Tu perds donc le véritable code de
retour du programme. Le "|| exit 1" est inutile (sans parler du ";").

- Synchronisation des données du fichier sur disque avec fsync(2) ;


Quelle drôle d'idée de forcer l'écriture sur disque d'un fichier temporaire.
C'est généralement une mauvaise idée.

- Fermeture du fichier avec close(2) ;
- Ajout des droits d'exécution au fichier avec un chmod(1) appelé via
system(3) ;


Cela aurait dû être fait par la fonction fchmod, surtout pas par l'exécution
d'un shell externe via la commande system.

- Execution du fichier avec system(3).

C'est lors de ce dernier appel que j'obtiens les codes d'erreur
suivants :

- Valeur de retour de system(3) : 256 ;
- Errno : 2 (No such file or directory) ;
- WEXITSTATUS(256) : 1.

Mes questions sont les suivantes :

- Comment interpréter ces codes d'erreur ?


La fonction system lance un shell et ce shell exécute la commande. Le code
de retour est celui du shell.

- A quoi correspond le '1' du WEXITSTATUS() ? Est-ce un '1' renvoyé
par le fichier temporaire sur échec d'exécution d'une commande shell
?


Comme tu ne dis pas exactement quelle commande tu as lancé, on ne peut
savoir.

- L'erreur 2 d'errno signifie-t-elle que mon fichier temporaire
n'existe finalement pas du tout ?


errno n'a pas à être testé après system, seul le code de retour doit l'être.
Voir le man.

Pour information, le code a été compilé avec gcc sans aucune
optimisation, et tourne sur une RedHat Entreprise 3.0 Update 6 (Noyau
2.4.21-37).


Si tu disais ce que tu exécutes dans ton shell, peut-être on pourrait savoir
ce qui ne vas pas. Le cas le plus typique est l'oublie d'un "./" avant un
shell-script vu que le PATH n'est pas toujours celui que l'on croit.

Teste ton shell-script directement sous shell en utilisant exactement les
mêmes variables d'environnement que celles qui sont utilisées _dans_ ton
programme C.

Merci pour vos éclaircissements, et pardonnez-moi si je n'ai pas
posté sur le bon groupe !


Poste la prochaine fois dans un NG lié à Linux ou unix.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.

Avatar
fponroy

Premièrement tout ce qui suit n'est pas du C standard et devrait être posté
sur un NG dédié à ta plateforme.


Salut Eric, merci pour ta réponse, et désolé pour le mauvais choix
de groupe !

J'ai un petit souci d'analyse des codes d'erreur de l'appel system(3).
Pour simplifier, la partie de mon code intéressante (et incriminée !)
effectue les opérations suivantes :


Si on tient à gérer finement le code de retour de system, alors on n' utilise
pas system mais fork/exec.

- Création d'un fichier temporaire avec mkstemp(3) ;
- Ajout de commandes au fichier avec plusieurs write(2) successifs.


Vu que tu écris du texte par ligne, le mieux aurait dû être d'utili se
fopen/fprintf/fclose...

Chaque ligne de commande ajoutée au fichier possède la syntaxe
suivante : commande shell || exit 1 ;


Bizarre comme commande : si ton shell part en erreur (ne retourne pas 0),
alors tu forces le code non nul à 1. Tu perds donc le véritable code de
retour du programme. Le "|| exit 1" est inutile (sans parler du ";").


Oui, je suis tout à fait d'accord avec toi, mais pour les besoins du
projet, on ne se soucie finalement pas du code de retour exact d'une
commande, on veut juste sortir en erreur dès qu'une commande échoue.
Si on ne précise pas '|| exit 1' après chaque commande, nous ne
sommes pas en mesure de savoir si une commande du script a échoué,
sachant que dans ce cas, le code de retour du script sera celui de la
dernière commande exécutée.
Concernant le « ; », il faisait juste partie de la ponctuation de mon
message :-)

- Synchronisation des données du fichier sur disque avec fsync(2) ;


Quelle drôle d'idée de forcer l'écriture sur disque d'un fichier te mporaire.
C'est généralement une mauvaise idée.


Au temps pour moi, je pensais sinon qu'il y avait des risques
d'exécuter le fichier avant que les données ne soient réellement
écrites dans le fichier. C'est sans aucun doute moi qui ne connais pas
assez les rouages du système d'exploitation pour avoir commis cette
faute impardonnable !

- Fermeture du fichier avec close(2) ;
- Ajout des droits d'exécution au fichier avec un chmod(1) appelé v ia
system(3) ;


Cela aurait dû être fait par la fonction fchmod, surtout pas par l'ex écution
d'un shell externe via la commande system.


Je vais corriger cela également.

- Execution du fichier avec system(3).

C'est lors de ce dernier appel que j'obtiens les codes d'erreur
suivants :

- Valeur de retour de system(3) : 256 ;
- Errno : 2 (No such file or directory) ;
- WEXITSTATUS(256) : 1.

Mes questions sont les suivantes :

- Comment interpréter ces codes d'erreur ?


La fonction system lance un shell et ce shell exécute la commande. Le c ode
de retour est celui du shell.

- A quoi correspond le '1' du WEXITSTATUS() ? Est-ce un '1' renvoyé
par le fichier temporaire sur échec d'exécution d'une commande shell
?


Comme tu ne dis pas exactement quelle commande tu as lancé, on ne peut
savoir.

- L'erreur 2 d'errno signifie-t-elle que mon fichier temporaire
n'existe finalement pas du tout ?


errno n'a pas à être testé après system, seul le code de retour d oit l'être.
Voir le man.

Pour information, le code a été compilé avec gcc sans aucune
optimisation, et tourne sur une RedHat Entreprise 3.0 Update 6 (Noyau
2.4.21-37).


Si tu disais ce que tu exécutes dans ton shell, peut-être on pourrait savoir
ce qui ne vas pas. Le cas le plus typique est l'oublie d'un "./" avant un
shell-script vu que le PATH n'est pas toujours celui que l'on croit.


Tout d'abord, toute commande du fichier est exécutée en précisant un
chemin absolu, ainsi que le script lui même. Ensuite (mais là, je
sors totalement du cadre de ce groupe), le script sort en erreur sur
exécution d'une commande de configuration d'un lien série avec stty.
Si cette commande est exécutée à la main, ou en lançant le script
complet, tout est OK. Le plus incompréhensible, c'est que cette erreur
est aléatoire. Si je relance mon programme, ça peut tomber en marche.
Si je remplace le binaire stty par un script portant le même nom
(coquille vide), ça marche également. Si tu as une idée là-dessus
et souhaites plus d'informations à ce sujet, nous pouvons volontiers
poursuivre sur un autre groupe (fr.comp.os.???).

Teste ton shell-script directement sous shell en utilisant exactement les
mêmes variables d'environnement que celles qui sont utilisées _dans_ ton
programme C.

Merci pour vos éclaircissements, et pardonnez-moi si je n'ai pas
posté sur le bon groupe !


Poste la prochaine fois dans un NG lié à Linux ou unix.


Y seras-tu ? :-)

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.



Avatar
Eric Levenez
Le 5/01/07 10:24, dans
,
«  » a écrit :


Si tu disais ce que tu exécutes dans ton shell, peut-être on pourrait savoir
ce qui ne vas pas. Le cas le plus typique est l'oublie d'un "./" avant un
shell-script vu que le PATH n'est pas toujours celui que l'on croit.


Tout d'abord, toute commande du fichier est exécutée en précisant un
chemin absolu, ainsi que le script lui même. Ensuite (mais là, je
sors totalement du cadre de ce groupe),


Tu n'as jamais été dans le cadre de ce NG qui ne parle que tu C standard.

le script sort en erreur sur
exécution d'une commande de configuration d'un lien série avec stty.
Si cette commande est exécutée à la main, ou en lançant le script
complet, tout est OK.


Regarde tous les variables d'environnement entre le lancement à la main et
le lancement automatique. La commande stty a un comportement qui change
suivant que stdin/out est ou non une vraie tty ou non.

Est-ce que ton programme qui fait le system utiliser le stdin/out (fermer,
redirigé...). As-tu fait un programme C tout court qui ne fait que la
fonction system ?

Le plus incompréhensible, c'est que cette erreur
est aléatoire. Si je relance mon programme, ça peut tomber en marche.


SI c'est aléatoire cela dépend donc de ce que fait le programme appelant et
de ce que fait le shell. Mais comme on n'a pas le code source, ni de l'un ni
de l'autre...

Si je remplace le binaire stty par un script portant le même nom
(coquille vide), ça marche également. Si tu as une idée là-dessus
et souhaites plus d'informations à ce sujet, nous pouvons volontiers
poursuivre sur un autre groupe (fr.comp.os.???).


Que donne la commande "tty" dans le shell entre un lancement manuel et par
system ?

Pourquoi ne pas utiliser les fonctions termios pour gérer le tty en C au
lieu de faire cela pas un programme externe ?

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.