2013-06-01 16 views
33

Ho un programma che utilizza diversi thread. A quanto ho capito, quando il thread 0 termina, l'intero programma si chiude, indipendentemente da altri thread che potrebbero ancora essere in esecuzione.Qual è il modo migliore per uscire da un programma Haskell?

Il problema è che questi altri thread potrebbero avere file aperti. Naturalmente, questo è incluso nel codice di gestione delle eccezioni che chiude in modo pulito i file in caso di problemi. Ciò significa anche che se utilizzo killThread (che è implementato tramite throwTo), il file dovrebbe anche essere chiuso prima che il thread esca.

La mia domanda è, se ho appena lasciato che il thread 0 esca, senza tentare di fermare gli altri thread, tutti i vari handle di file saranno chiusi bene? L'output bufferizzato viene scaricato?

In breve, posso uscire o devo prima eliminare manualmente i thread?

+2

Preferisco non fare affidamento su 'killThread' o' exit' per pulire altri thread solo per una buona igiene di programmazione. Io strumento tutti i miei thread per ascoltare i segnali di pulizia dal thread principale in modo che possano essere tutti chiusi con grazia. –

+0

Perché non provarlo? IME, la maggior parte dei sistemi operativi chiuderà i file, ovvero non lascerà alcun handle, fd o altre perdite, ma l'I/O in sospeso non verrà scaricato. –

+1

@GabrielGonzalez Se lo fai in questo modo, significa che un thread terminerà solo in determinati punti.Se ti dimentichi di controllare regolarmente abbastanza, o qualcosa richiede più tempo del previsto, puoi ottenere una situazione in cui segnali il thread di morire, e non lo fa (o richiede solo molto tempo). Devi comunque gestire le eccezioni, quindi perché non usare 'killThread'? – MathematicalOrchid

risposta

3

Dal mio test, ho scoperto un paio di cose:

  1. exitFailure e amici funzionare solo in discussione 0. (La documentazione dice in realtà così, se si va alla briga di leggerlo Queste funzioni. basta gettare eccezioni, che sono silenziosamente ignorati in altri thread.)

  2. Se un'eccezione uccide il tuo thread, o intero il vostro programma, eventuali handle aperti sono non arrossato. Questo è terribilmente fastidioso quando stai cercando disperatamente di capire esattamente dove si è verificato il crash del tuo programma!

così sembra, se si desidera che la roba lavata prima che il programma si chiude, quindi si devi implementare questa. Lasciare che il thread 0 muoia non svuota la roba, non genera eccezioni, termina silenziosamente tutti i thread senza eseguire gestori di eccezioni.

3

È possibile utilizzare Control.Concurrent.MVar per ottenere ciò. Un MVar è essenzialmente un flag che è "vuoto" o "pieno". Un thread può provare a leggere un MVar e se è vuoto blocca il thread. Ovunque tu abbia un thread che esegue il file IO, crea un MVar per esso e passalo come argomento a MVar. Mettere tutte le MVar s si crea in una lista:

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])) 

Una volta che un thread figlio ha terminato tutte le operazioni sui file che si sono preoccupati, scrivere al MVar. Invece di scrivere killThread si può fare

mapM_ takeMVar mvars >> killThread 

e dove mai il tuo thread dovrebbe uscire in caso contrario, basta prendere tutte le MVar s.

Vedere documentation on GHC concurrency per ulteriori dettagli.

+3

Penso che stia facendo una domanda diversa: come interrompere i thread figlio con garbo se il thread master è terminato e non vuole più attendere i risultati. Nota a margine: puoi fare ciò che descrivi usando il pacchetto 'async', che ha anche il vantaggio aggiuntivo di sollevare nuovamente le eccezioni create nei thread figli se ti" aspetti "su di loro. –

+0

Mentre lo leggevo, è preoccupato che quando il thread parent esca, i bambini usciranno anche, forse causando effetti collaterali indesiderati se stanno scrivendo su file. Se il thread principale attende che i suoi figli finiscano tutte le operazioni di I/O sui file, questo cessa di essere un problema. – user2407038

Problemi correlati