How can I fork standard output?

I have a program that I want to run and wait for it to initialize before proceeding, but I also want the program to write to the terminal as usual, which it would do if I simply called it with callProcess. To this end, I have devised the following hack:

(In this case I listen to the standard error, but I suppose this is inessential.)

  …
  withCreateProcess applicationProcessDescription \ _ _ maybeApplicationStdErr _ -> do
    case maybeApplicationStdErr of
      Nothing -> throwIO $ DeploymentException $ "Unable to grab application's standard error stream!"
      Just applicationStdErr -> do
        maybeTimeout <- timeout waitingTime (waitForApplication applicationStdErr)
        when (isNothing maybeTimeout) $ throwIO $ DeploymentException $ "Application took too long initializing!"
        redirectHandle applicationStdErr stderr
        …

waitForApplication :: Handle -> IO ( )
waitForApplication stdErr = do
  line <- hGetLine stdErr
  hPutStrLn stderr line
  if line == "Application initialized."
    then return ( )
    else waitForApplication stdErr

redirectHandle :: Handle -> Handle -> IO ( )
redirectHandle from to = void $ forkFinally
  do forever do
      line <- hGetLine from
      hPutStrLn to line
  \ _ -> return ( )

I intercept whatever the subprocess is saying, line by line, analyze the lines in some way and put them to the main process's standard error. When I am done, I still have to keep listening and relaying. This seems like an absurd way of going about it.

What I would like to do is fork the subprocess's standard error stream in some way, so that I may eavesdrop on it passively while I need to, and then simply disconnect. It is important for me that whatever the subprocess is saying was delivered to the human as faithfully as possible — without delay and omission.

Is there a nice way to do it?