Question

CreateFile de Win32 a> a FILE_FLAG_DELETE_ON_CLOSE , mais je suis sous Linux.

Je souhaite ouvrir un fichier temporaire qui sera toujours supprimé à la fin du programme. Je pourrais comprendre qu’en cas de blocage du programme, il ne soit pas pratique de le garantir, mais dans tous les autres cas, j’aimerais que cela fonctionne.

Je connais RAII. Je connais les signaux. Je connais atexit (3) . Je sais que je peux ouvrir le fichier et le supprimer immédiatement et que le fichier restera accessible jusqu'à la fermeture du descripteur de fichier (qui gère même un blocage). Aucune de ces solutions ne semble complète et simple:

  1. RAII: y a été, cela fait: j’ai un objet dont le destructeur supprime le fichier, mais le destructeur n’est pas appelé si le programme se termine par un signal.
  2. signaux: J'écris une bibliothèque de bas niveau qui rend l'enregistrement d'un gestionnaire de signal une proposition délicate. Par exemple, que se passe-t-il si l'application utilise elle-même des signaux? Je ne veux pas marcher sur les orteils. Je pourrais envisager une utilisation intelligente de sigaction (2) pour y faire face ... mais je n'ai pas encore réfléchi à cette possibilité.
  3. atexit (3) : apparemment inutile, car il n'est pas appelé pendant une terminaison anormale (par exemple via un signal).
  4. préemptif unlink (2) : c'est plutôt bon sauf que j'ai besoin que le fichier reste visible dans le système de fichiers (sinon, le système est plus difficile à surveiller / à résoudre).

Que feriez-vous ici?

Explication complémentaire

J'ai élidé un détail dans mon message original que je réalise maintenant que j'aurais dû l'inclure. Le " fichier " dans ce cas, ce n’est pas strictement un fichier normal, mais plutôt une file de messages POSIX. Je le crée via mq_open () . Il peut être fermé via mq_close () ou close () (le premier est un alias pour le dernier sur mon système). Il peut être supprimé du système via mq_unlink () . Tout cela le rend analogue à un fichier normal, sauf que je ne peux pas choisir le répertoire dans lequel réside le fichier. Cela rend la réponse la plus populaire actuelle (placer le fichier dans / tmp ) inutilisable, car le fichier "" fichier". est créé par le système dans un système de fichiers virtuel avec une capacité très limitée. (J'ai monté le système de fichiers virtuel dans / dev / mqueue , en suivant l'exemple présenté dans man mq_overview ).

Cela explique également pourquoi j'ai besoin de garder le nom visible (rendant l’approche de suppression immédiate du lien irréalisable): le fichier "Fichier". doivent être partagés entre deux processus ou plus.

Était-ce utile?

La solution

L'exigence que le nom reste visible pendant que le processus est en cours rend cela difficile à atteindre. Pouvez-vous revenir sur cette exigence?

Si ce n’est pas le cas, il n’ya probablement pas de solution parfaite. J'envisagerais de combiner une stratégie de traitement du signal avec ce que suggère Kamil Kisiel. Vous pouvez suivre les gestionnaires de signaux installés avant d’installer vos gestionnaires de signaux. Si le gestionnaire par défaut est SIG_IGN, vous n'installez normalement pas votre propre gestionnaire. si c'est SIG_DFL, vous vous en souviendrez; S'il s'agit de quelque chose d'autre - un gestionnaire de signal défini par l'utilisateur - vous vous souviendrez de ce pointeur et installerez le vôtre. Lorsque votre gestionnaire a été appelé, vous faites ce que vous devez faire, puis appelez le gestionnaire mémorisé, ce qui vous permet d'enchaîner les gestionnaires. Vous devez également installer un gestionnaire atexit (). Vous voudriez également documenter le fait que vous le faites et les signaux pour lesquels vous le faites.

Notez que la gestion du signal est une stratégie imparfaite. SIGKILL ne peut pas être attrapé, et le gestionnaire atexit () ne sera pas appelé et le fichier sera laissé.

La suggestion de David Segond - un démon de nom de fichier temporaire - est intéressante. Pour des processus simples, cela suffit; si le processus qui demande le fichier temporaire demande et que l'enfant soit ensuite propriétaire du fichier (et le quitte), le démon a un problème pour détecter la fin du dernier processus qui l'utilise, car il ne connaît pas automatiquement les processus qui l'ont ouvert.

Autres conseils

Si vous créez simplement un fichier temporaire, créez-le simplement dans / tmp ou l'un de ses sous-répertoires. Efforcez-vous ensuite de le supprimer via atexit (3) ou similaire. Tant que vous utilisez des noms uniques choisis dans mkstemp (3) ou similaire, même s'il ne parvient pas à être supprimés en raison d'un blocage du programme, vous ne risquez pas de le relire lors d'exécutions ultérieures ou autres. .

À ce stade, il s’agit simplement d’un problème au niveau du système consistant à maintenir / tmp propre. La plupart des distributions l’effacent au démarrage ou à l’arrêt, ou exécutent une tâche régulière pour supprimer les anciens fichiers.

Peut-être que quelqu'un a déjà suggéré cela, mais je ne parviens pas à le repérer, étant donné toutes vos exigences, le mieux que je puisse faire est de faire en sorte que le nom du fichier soit communiqué à un processus parent, tel qu'un script de démarrage, qui nettoyer après la mort du processus, s’il ne l’avait pas fait. Ceci est peut-être principalement connu comme un chien de garde, mais avec le cas d'utilisation plus commun ajouté pour tuer et / ou redémarrer le processus quand il échoue.

Si votre processus parent meurt également, vous avez peu de chance, mais la plupart des environnements de script sont relativement robustes et ne meurent que rarement, à moins que le script ne soit interrompu, ce qui est souvent plus facile à maintenir qu'un programme.

Par le passé, j'ai créé un "gestionnaire de fichiers temporaires". qui garde trace des fichiers temporaires.

On demande un nom de fichier temporaire au gestionnaire et ce nom est enregistré.

Une fois que vous n'avez plus besoin du nom de fichier temporaire, vous en informez le responsable et le nom du fichier n'est pas enregistré.

À la réception d'un signal de fin, tous les fichiers temporaires enregistrés ont été détruits.

Les noms de fichiers temporaires étaient basés sur un UUID pour éviter les collisions.

Vous pouvez avoir le processus fork après la création du fichier, puis attendre la fermeture de l'enfant, puis le parent peut dissocier le fichier et quitter.

Je viens de rejoindre stackoverflow et je vous ai trouvé ici:)

Si votre problème est de gérer les fichiers mq et de les empêcher de s’empiler, vous n’avez pas vraiment besoin de garantir la suppression des fichiers lors de la résiliation. Si vous vouliez simplement accumuler des fichiers inutiles, il vous suffirait peut-être de tenir un journal. Ajoutez une entrée au fichier journal après l’ouverture d’un fichier mq, une autre entrée lors de la fermeture et l’initialisation de votre bibliothèque, vérifiez la présence d’incohérence dans le journal et prenez les mesures nécessaires pour corriger cette incohérence. Si vous craignez un blocage lors de l'appel de mq_open / mq_close , vous pouvez également ajouter une entrée de journal juste avant l'appel de ces fonctions.

  • Ayez un répertoire de comptabilité pour les fichiers temporaires sous votre répertoire de points.
  • Lors de la création d'un fichier temporaire, commencez par créer un fichier de comptabilité dans le répertoire contenant le chemin d'accès ou l'UUID de votre futur fichier temporaire.
  • Créez ce fichier temporaire.
  • Lorsque le fichier temporaire est supprimé, supprimez le fichier de comptabilité.
  • Lorsque le programme démarre, recherchez dans le répertoire de comptabilité tous les fichiers contenant des chemins d'accès aux fichiers temporaires et essayez de les supprimer, le cas échéant, supprimez les fichiers de comptabilité.
  • (Connectez-vous bruyamment si une étape échoue.)

Je ne vois aucun moyen de le faire plus simple. C'est le passe-partout par lequel tout programme de qualité de la production doit passer; +500 lignes facilement.

scroll top