2 votes

Les dangers de la fermeture des descripteurs de fichiers

Dans la question de Stack Overflow Vérifier si un programme existe à partir d'un bash script. el réponse acceptée note que la fermeture de stderr est dangereuse :

(petite remarque : certains suggèrent que 2>&- est la même chose que 2>/dev/null mais en plus court - c'est faux. 2>&- ferme le FD 2, ce qui provoque une erreur dans le programme lorsqu'il tente d'écrire sur stderr, ce qui est très différent d'une écriture réussie et de la mise au rebut de la sortie (et dangereux !)).

  • En dehors d'une erreur dans le programme d'écriture, quelles autres choses dangereuses pourraient se produire ?
  • L'utilisation de 2>&- peut-elle potentiellement interrompre le programme en cours d'écriture (c'est-à-dire arrêter son exécution et ne pas permettre le nettoyage) ?

9voto

Ryan Sampson Points 2898

Oui, il va casser des choses, de manière passionnante et intéressante.

Le problème est que les systèmes de type Unix allouent généralement les descripteurs de fichiers de manière séquentielle. Quand un programme veut un nouveau descripteur de fichier (c'est-à-dire qu'il appelle open() , socket() et toute autre fonction qui alloue un fd), le noyau trouvera le descripteur "libre" ayant le numéro le plus bas, et le distribuera.

Imaginez maintenant, si vous le voulez bien, que vous avez fermé fd 2 (stderr). Quelque chose dans le processus veut alors un descripteur de fichier (le prochain fichier ouvert). Le noyau cherche un fd libre, voit que fd 2 est inutilisé, et le rend au programme.

Maintenant, imaginez que quelque chose d'autre dans le programme veuille écrire sur stderr. Il écrit aveuglément sur fd 2, parce que c'est là que se trouve stderr. Sauf que maintenant ce n'est plus le cas. Si vous êtes chanceux , fd 2 a été ouvert en lecture seule, et l'écriture obtient une erreur. Tout le monde suppose que les écritures sur stderr réussissent toujours, donc ça va être amusant. Mais il est au moins aussi probable que le fd soit ouvert en lecture-écriture (cinq des six fd de l'interface utilisateur sont ouverts en lecture seule). fopen (2) les modes sont activés en écriture -- r+ , a , a+ , w ou w+ ) et le message qui était censé aller dans stderr a juste fini par être éclaboussé dans whoknowswhere .

Encore plus excitant, les *descripteurs de fichiers sont hérités sur fork() . Cela signifie que chaque Le processus de l'enfant aura également la possibilité de griffonner dans un endroit inattendu. Pire, même les stratégies de bifurcation "sûres", par exemple lorsque tous les fd sont fermés avant que exec ne touchent généralement pas les fds 0, 1 ou 2. Ainsi, votre petite casse survivra presque certainement aux stratégies ordinaires destinées à prévenir les catastrophes à travers les frontières du processus.

Vous pourriez dire : "Dans ce cas, je n'utiliserai jamais une bibliothèque qui écrit sur stderr, et je ferai attention à ne jamais écrire moi-même sur stderr". À cela, je n'ai que deux choses à dire :

  1. Dans le futur, tu ne seras pas aussi prudent. Vous oublierez que vous avez fermé stderr.
  2. Tout le monde sinon qui auront un jour le malheur de traiter avec votre code fou ne seront pas non plus très prudents.

Les amis ne laissent pas leurs amis fermer stderr. La Womble est sortie. laisse tomber le micro

1voto

Navern Points 1569

Cela peut être très, très mauvais et conduire à un comportement indéfini. Consultez mon ancienne question : La réplication MySQL s'arrête après la rotation du binlog .

Nous avions fermé le fd 2 pour le démon mysql et les messages d'aide étaient écrits dans binlog.info. Cela a cassé la réplication maître-esclave.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X