Bash et les bugs

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour, J'étudie bash dans le but de reprogrammer un shell.

D'après vous si on fait ls | cat. ls et cat sont exécuter en même temps ou l'un après l'autre ?

Je connais la réponse1, c'est juste que je trouve ça contre intuitif alors dites ce que vous pensez sans allez vérifier.

J'ai examiné bash à coup de strace. J'ai donc fait : strace bash -c "echo qsd | cat" 2>&1 | grep "close" Le résultat :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(3)                                = 0
close(4)                                = 0
close(4)                                = -1 EBADF (Bad file descriptor)
close(3)                                = 0
close(3)                                = -1 EBADF (Bad file descriptor)

Apparemment, bash ferme 2 fois d'affiler un même fichier et ça retourne une erreur. Est-ce normal ?

Merci d'avance :)

Édité par ache

ache.one                                                                                   🦊

+0 -0

Ils sont bien exécutés en même temps.

Sans rentrer dans les détails1, le principe des tubes (pipes en anglais) sous UNIX consiste à « connecter » la sortie standard de la commande de gauche vers l'entrée standard de la commande à droite du symbole |.

Les close que tu vois correspondent aux fermetures des fichiers de sortie standard et de fermeture standard (car oui, même l'entrée standard, la sortie standard et la sortie d'erreur sont des fichiers !) :)


  1. Les tubes mériteraient à eux seuls un tutoriel, je pense ^^ 

Édité par Jérôme Deuchnord

A graphical interface is like a joke: if you have to explain it, that's shit. | Les logiciels Deuchnord

+0 -0
Auteur du sujet

Parfait. Donc c'est normal. C'est moi qui avait mal compris x)

Et pour les close, du coup pourquoi ça entraîne une erreur ? Je veux dire si ça retourne 'Bad file descriptor' de manière systématique, c'est qu'il y a un problème non ?

Édité par ache

ache.one                                                                                   🦊

+0 -0

Là, par contre, je penche pour le bug dans Bash, j'ai la même chose chez moi ^^

Ce qu'il appelle file descriptor (ou descripteur de fichier) correspond à un numéro d'identification vers un fichier ouvert. En C, il est généré par la fonction open(). Il s'agit bien sûr d'une fonction très bas niveau, ce qui explique probablement son utilisation par Bash qui a besoin de travailler au niveau du système.

Édité par Jérôme Deuchnord

A graphical interface is like a joke: if you have to explain it, that's shit. | Les logiciels Deuchnord

+0 -0

En fouillant un peu, ces file descriptors sont en fait créés par la fonction pipe, et le bug a l'air a l'air d'en être un.

Cette fonction permet de créer deux file descriptors tels qu'on peut lire dans le premier ce qu'on écrit dans le deuxième.

Pour les plus curieux et téméraires, allez voir la fonction execute_pipeline dans le fichier execute_cmd.c des sources de bash.

Et le report de bug qui va bien sur la mailing-list de bug de bash : http://lists.gnu.org/archive/html/bug-bash/2015-12/msg00059.html

Édité par Nheir

+0 -0

Je confirme le "bug", j'ai la même chose chez moi avec bash 4.3.42(1)-release de Debian. Par contre, ça me fait pas ça avec zsh. Tu peux peut-être poser la question sur la mailing-list de bash.

Sinon, pour ce qui est d'apprendre comment un shell fonctionne, j'utiliserais pas bash parce que c'est énorme. Je me baserais plutôt sur le shell du projet xv6, qui est un OS basé sur Unix v6 qui sert à un cours sur les OS au MIT: xv6. Le code est libre et il y a un PDF disponible sur le site expliquant son fonctionnement, si ça intéresse quelqu'un.

+0 -0
Auteur du sujet

J'ai essayé de poster sur bug-bash@gnu.org. Mais rien n’apparaît sur https://lists.gnu.org/archive/html/bug-bash/

Merci pour xv6, ça me serra certainement utile pour des détails comme celui-ci.

ache.one                                                                                   🦊

+0 -0

Je confirme le "bug", j'ai la même chose chez moi avec bash 4.3.42(1)-release de Debian. Par contre, ça me fait pas ça avec zsh. Tu peux peut-être poser la question sur la mailing-list de bash.

Sinon, pour ce qui est d'apprendre comment un shell fonctionne, j'utiliserais pas bash parce que c'est énorme. Je me baserais plutôt sur le shell du projet xv6, qui est un OS basé sur Unix v6 qui sert à un cours sur les OS au MIT: xv6. Le code est libre et il y a un PDF disponible sur le site expliquant son fonctionnement, si ça intéresse quelqu'un.

Grimur

Pour ma part, l'an dernier, en licence, j'avais eu à faire un petit shell (sans grande prétention, c'était dans le cadre d'un TP) en C. Pas évident, mais ça permet de comprendre pas mal de choses :)

A graphical interface is like a joke: if you have to explain it, that's shit. | Les logiciels Deuchnord

+0 -0

Je confirme le "bug", j'ai la même chose chez moi avec bash 4.3.42(1)-release de Debian. Par contre, ça me fait pas ça avec zsh. Tu peux peut-être poser la question sur la mailing-list de bash.

Sinon, pour ce qui est d'apprendre comment un shell fonctionne, j'utiliserais pas bash parce que c'est énorme. Je me baserais plutôt sur le shell du projet xv6, qui est un OS basé sur Unix v6 qui sert à un cours sur les OS au MIT: xv6. Le code est libre et il y a un PDF disponible sur le site expliquant son fonctionnement, si ça intéresse quelqu'un.

Grimur

Pour ma part, l'an dernier, en licence, j'avais eu à faire un petit shell (sans grande prétention, c'était dans le cadre d'un TP) en C. Pas évident, mais ça permet de comprendre pas mal de choses :)

Jérôme Deuchnord

T'as un bout de code à nous partager ?

+0 -0

Voici

A priori, le shell fonctionne à peu près, il permet de lancer certaines commandes (pas toutes, certaines sont stoppées, sans que je sache pourquoi). Il est possible d'envoyer les contrôles clavier Ctrl + C (signal SIGINT) et Ctrl + Z (signal SIGTSTP)1. Certaines commandes propres au shell (comme fg et bg) ne fonctionnent pas et provoquent un signal SIGSEGV1.

Voili voilu :)

N'hésitez pas à demander si quelque chose n'est pas compris. Je ne garantie pas de toujours pouvoir répondre (ça date de plus d'un an quand même), mais bon ^^


  1. Voir man 7 signal pour plus d'infos sur les signaux supportés sous UNIX. 

Édité par Jérôme Deuchnord

A graphical interface is like a joke: if you have to explain it, that's shit. | Les logiciels Deuchnord

+0 -0
Auteur du sujet

Alors du coup, sur la mailing-list bug-bash gnu.org on m'a répondu que c'est comme ça que bash vérifiait que le descripteur de fichier est bien fermé. C'est curieux comme méthode m'enfin.

@Jérome Deuchnord: Je me permet du coup de regarder. J'ai étudié un peu les signaux mais pas comment capturer Crtl+C.

On a également un shell à faire comme exercice, il est bientôt fini ^^ On doit également recoder quelques commandes en plus des build-in de bases. Comme cat, less, ps, top et même su.

Édité par ache

ache.one                                                                                   🦊

+0 -0

@Jérome Deuchnord: Je me permet du coup de regarder. J'ai étudié un peu les signaux mais pas comment capturer Crtl+C.

Regarde dans le fichier mshell.c (qui contient la fonction main()), au niveau des lignes 248 à 250, tu as ceci :

1
2
3
  signal_wrapper(SIGINT,  sigint_handler);   /* ctrl-c */
  signal_wrapper(SIGTSTP, sigtstp_handler);  /* ctrl-z */
  signal_wrapper(SIGCHLD, sigchld_handler);  /* Terminated or stopped child */

Ce sont ces lignes qui permettent de rattraper les Ctrl + C et Ctrl + Z (la troisième permet de gérer le fait qu'un processus lancé dans le shell se soit terminé ou stoppé1). Les signaux générés sont récupérées dans la fonction sigchld_handler() définie dans le fichier sighandlers.c (ligne 49). Si je me souviens bien, quand tu envoies un signal au processus (par exemple si tu fais Ctrl + C pendant l'exécution d'une commande), c'est lui qui va gérer le signal reçu et non le shell.

Ce dernier se contente de vérifier si la commande est toujours en cours d'exécution, s'il s'est arrêté, s'il s'est terminé ou s'il a été tué (le processus retourne toujours cette information à son processus père, i.e. le shell). Dans le cas où un processus s'est terminé, le shell doit également s'occuper de le supprimer, à défaut de quoi le processus fils deviendra zombie2.

Voilà, en espérant avoir répondu à ta question :)

Bon courage :)


  1. On dit qu'un processus est stoppé lorsqu'il se met en pause. Le processus devient alors incapable de répondre. 

  2. Un zombie est un processus dont le père n'a pas encore géré le fait qu'il se soit terminé. 

A graphical interface is like a joke: if you have to explain it, that's shit. | Les logiciels Deuchnord

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte