<commit_before>module Streamero.Process (
    OutputHandler
  , proc
  , CreateProcess
  , ProcessHandle
  , createProcess
  , withProcess
) where

import           Control.Monad (unless, void)
import           Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar)
import           Control.Exception (onException, throw)
import           System.Exit (ExitCode(..))
import           System.IO (Handle)
import qualified System.IO as IO
import           System.Process (CreateProcess, ProcessHandle, terminateProcess, waitForProcess)
import qualified System.Process as P

type OutputHandler = String -> IO ()

pipeOutput :: OutputHandler -> Handle -> IO ()
pipeOutput f h = IO.hIsEOF h >>= flip unless (IO.hGetLine h >>= f >> pipeOutput f h)

proc :: FilePath -> [String] -> CreateProcess
proc cmd args = (P.proc cmd args) { P.std_out = P.CreatePipe
                                  , P.std_err = P.CreatePipe }

createProcess :: OutputHandler -> CreateProcess -> IO ProcessHandle
createProcess handleOutput spec = do
    (_, maybeStdout, maybeStderr, pid) <- P.createProcess spec
    maybe (return ()) (void . forkIO . pipeOutput handleOutput) maybeStdout
    maybe (return ()) (void . forkIO . pipeOutput handleOutput) maybeStderr
    return pid

withProcess :: OutputHandler -> CreateProcess -> IO a -> IO a
withProcess handleOutput spec action = do
    pid <- createProcess handleOutput spec
    exitCode <- newEmptyMVar
    void $ forkIO $ waitForProcess pid >>= putMVar exitCode
    a <- action `onException` do
        terminateProcess pid
        -- Wait for process termination
        takeMVar exitCode
    e <- takeMVar exitCode
    case e of
        ExitSuccess -> return a
        ExitFailure _ -> throw e<commit_msg>Terminate process when action finishes in 'withProcess'<commit_after>module Streamero.Process (
    OutputHandler
  , proc
  , CreateProcess
  , ProcessHandle
  , createProcess
  , withProcess
) where

import           Control.Monad (unless, void)
import           Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar)
import           Control.Exception (finally, throw)
import           System.Exit (ExitCode(..))
import           System.IO (Handle)
import qualified System.IO as IO
import           System.Process (CreateProcess, ProcessHandle, terminateProcess, waitForProcess)
import qualified System.Process as P

type OutputHandler = String -> IO ()

pipeOutput :: OutputHandler -> Handle -> IO ()
pipeOutput f h = IO.hIsEOF h >>= flip unless (IO.hGetLine h >>= f >> pipeOutput f h)

proc :: FilePath -> [String] -> CreateProcess
proc cmd args = (P.proc cmd args) { P.std_out = P.CreatePipe
                                  , P.std_err = P.CreatePipe }

createProcess :: OutputHandler -> CreateProcess -> IO ProcessHandle
createProcess handleOutput spec = do
    (_, maybeStdout, maybeStderr, pid) <- P.createProcess spec
    maybe (return ()) (void . forkIO . pipeOutput handleOutput) maybeStdout
    maybe (return ()) (void . forkIO . pipeOutput handleOutput) maybeStderr
    return pid

withProcess :: OutputHandler -> CreateProcess -> IO a -> IO a
withProcess handleOutput spec action = do
    pid <- createProcess handleOutput spec
    exitCode <- newEmptyMVar
    void $ forkIO $ waitForProcess pid >>= putMVar exitCode
    a <- action `finally` terminateProcess pid
    e <- takeMVar exitCode
    case e of
        ExitSuccess -> return a
        ExitFailure _ -> throw e
{'fraction_non_alphanumeric': 0.08812372337321273, 'fraction_numerical': 0.0, 'mean_word_length': 2.944764096662831, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6245018', 'n_tokens_mistral': 950, 'n_tokens_neox': 924, 'n_words': 314}