33 votes

Quelle est la meilleure façon de quitter un programme Haskell ?

J'ai un programme qui utilise plusieurs threads. Si je comprends bien, lorsque le thread 0 se termine, le programme entier se termine, sans tenir compte des autres threads qui pourraient encore être en cours d'exécution.

Le problème est que ces autres fils peuvent avoir des fichiers ouverts. Naturellement, ceci est enveloppé dans un code de gestion des exceptions qui ferme proprement les fichiers en cas de problème. Cela signifie également que si j'utilise killThread (qui est mis en œuvre via throwTo ), le fichier doit également être fermé avant que le fil ne se termine.

Ma question est la suivante : si je laisse simplement le thread 0 sortir, sans essayer d'arrêter les autres threads, est-ce que tous les différents handles de fichiers seront bien fermés ? Est-ce que toute sortie en mémoire tampon sera vidée ?

En bref, puis-je simplement quitter, ou dois-je d'abord tuer manuellement les fils ?

4voto

user2407038 Points 4636

Vous pouvez utiliser Control.Concurrent.MVar pour y parvenir. Un site MVar est essentiellement un drapeau qui est soit ''vide'' soit ''plein''. Un thread peut essayer de lire un MVar et s'il est vide, il bloque le fil. Partout où vous avez un thread qui effectue des entrées/sorties de fichiers, créez un fichier MVar pour elle, et la faire passer que MVar comme argument. Mettez tous les MVar que vous créez dans une liste :

main = do
  let mvars = sequence (replicate num_of_child_threads newEmptyMVar)
  returnVals <- sequence (zipWith (\m f -> f m) 
                                  mvars 
                                  (list_of_child_threads :: [MVar -> IO a])) 

Une fois qu'un thread enfant a terminé toutes les opérations sur les fichiers qui vous préoccupent, écrivez dans le fichier MVar . Au lieu d'écrire killThread vous pouvez faire

mapM_ takeMVar mvars >> killThread 

et à l'endroit où votre fil se terminerait autrement, prenez juste tous les éléments suivants MVar s.

Voir le documentation sur la concurrence dans GHC pour plus de détails.

3voto

MathematicalOrchid Points 15354

Mes essais m'ont permis de découvrir plusieurs choses :

  1. exitFailure et ses amis ne fonctionnent que dans le fil d'exécution 0. (La documentation le précise, si vous vous donnez la peine de la lire. Ces fonctions ne font que lancer des exceptions, qui sont silencieusement ignorées dans les autres threads).

  2. Si une exception tue votre thread, ou votre programme entier, tous les handles ouverts sont pas rougis. C'est terriblement ennuyeux lorsque vous essayez désespérément de déterminer l'endroit exact où votre programme s'est planté !

Il semble donc que si vous voulez que vos affaires soient effacées avant que le programme ne se termine, alors vous doivent le mettre en œuvre. Le fait de laisser mourir le thread 0 n'entraîne pas de purge, ne lève aucune exception, mais met fin silencieusement à tous les threads sans exécuter de gestionnaire d'exception.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X