diff --git a/compiler/GHC/Runtime/Interpreter.hs b/compiler/GHC/Runtime/Interpreter.hs index a0436e56ea044abe3c8c0a96ac8825caf2c7cd0d..dd57812b52dc0d8453b74790d846afdb2cb9f1aa 100644 --- a/compiler/GHC/Runtime/Interpreter.hs +++ b/compiler/GHC/Runtime/Interpreter.hs @@ -108,7 +108,6 @@ import Control.Monad.Catch as MC (mask) import Data.Binary import Data.ByteString (ByteString) import Data.Array ((!)) -import Data.IORef import Foreign hiding (void) import qualified GHC.Exts.Heap as Heap import GHC.Stack.CCS (CostCentre,CostCentreStack) @@ -577,12 +576,11 @@ spawnIServ conf = do (ph, rh, wh) <- runWithPipes createProc (iservConfProgram conf) [] (iservConfOpts conf) - lo_ref <- newIORef Nothing + interpPipe <- mkPipeFromHandles rh wh lock <- newMVar () - let pipe = Pipe { pipeRead = rh, pipeWrite = wh, pipeLeftovers = lo_ref } let process = InterpProcess { interpHandle = ph - , interpPipe = pipe + , interpPipe , interpLock = lock } diff --git a/compiler/GHC/Runtime/Interpreter/JS.hs b/compiler/GHC/Runtime/Interpreter/JS.hs index 64b0d7ff3533b45ceaed014072765c3928b5f9c2..52b58b568aceda14d137562b0ecebaa71dc428ef 100644 --- a/compiler/GHC/Runtime/Interpreter/JS.hs +++ b/compiler/GHC/Runtime/Interpreter/JS.hs @@ -129,12 +129,11 @@ startTHRunnerProcess interp_js settings = do (nodeExtraArgs settings) std_in <- readIORef interp_in - lo_ref <- newIORef Nothing + interpPipe <- mkPipeFromHandles rh wh lock <- newMVar () - let pipe = Pipe { pipeRead = rh, pipeWrite = wh, pipeLeftovers = lo_ref } let proc = InterpProcess { interpHandle = hdl - , interpPipe = pipe + , interpPipe , interpLock = lock } pure (std_in, proc) diff --git a/compiler/GHC/Runtime/Interpreter/Wasm.hs b/compiler/GHC/Runtime/Interpreter/Wasm.hs index d2c7bfb19d86cbecf2f80e8b73cfa09a4c005d57..a6dd9513bc7e8f0fa1da9b9cc7469508421fe376 100644 --- a/compiler/GHC/Runtime/Interpreter/Wasm.hs +++ b/compiler/GHC/Runtime/Interpreter/Wasm.hs @@ -10,7 +10,6 @@ import GHC.Runtime.Interpreter.Types #if !defined(mingw32_HOST_OS) import Control.Concurrent.MVar -import Data.IORef import GHC.Data.FastString import qualified GHC.Data.ShortText as ST import GHC.Platform @@ -60,7 +59,7 @@ spawnWasmInterp WasmInterpConfig {..} = do wh <- Posix.fdToHandle wfd2 hSetBuffering wh NoBuffering hSetBuffering rh NoBuffering - lo_ref <- newIORef Nothing + interpPipe <- mkPipeFromHandles rh wh pending_frees <- newMVar [] lock <- newMVar () pure @@ -68,7 +67,7 @@ spawnWasmInterp WasmInterpConfig {..} = do { instProcess = InterpProcess { interpHandle = ph, - interpPipe = Pipe {pipeRead = rh, pipeWrite = wh, pipeLeftovers = lo_ref}, + interpPipe, interpLock = lock }, instPendingFrees = pending_frees, diff --git a/libraries/ghci/GHCi/Message.hs b/libraries/ghci/GHCi/Message.hs index b745bdb536ee83b8e45cb559f41aacf27d4a10c1..2de17797c34068509f3bca85b5b47984429b3e11 100644 --- a/libraries/ghci/GHCi/Message.hs +++ b/libraries/ghci/GHCi/Message.hs @@ -1,6 +1,6 @@ {-# LANGUAGE GADTs, DeriveGeneric, StandaloneDeriving, ScopedTypeVariables, GeneralizedNewtypeDeriving, ExistentialQuantification, RecordWildCards, - CPP #-} + CPP, NamedFieldPuns #-} {-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-orphans #-} -- | @@ -21,7 +21,7 @@ module GHCi.Message , ResumeContext(..) , QState(..) , getMessage, putMessage, getTHMessage, putTHMessage - , Pipe(..), remoteCall, remoteTHCall, readPipe, writePipe + , Pipe, mkPipeFromHandles, remoteCall, remoteTHCall, readPipe, writePipe , BreakModule , LoadedDLL ) where @@ -48,6 +48,7 @@ import Data.Binary.Get import Data.Binary.Put import Data.ByteString (ByteString) import qualified Data.ByteString as B +import qualified Data.ByteString.Builder as B import qualified Data.ByteString.Lazy as LB import Data.Dynamic import Data.Typeable (TypeRep) @@ -644,47 +645,52 @@ serializeBCOs rbcos = parMap doChunk (chunkList 100 rbcos) -- ----------------------------------------------------------------------------- -- Reading/writing messages +-- | An opaque pipe for bidirectional binary data transmission. data Pipe = Pipe - { pipeRead :: Handle - , pipeWrite :: Handle - , pipeLeftovers :: IORef (Maybe ByteString) + { getSome :: !(IO ByteString) + , putAll :: !(B.Builder -> IO ()) + , pipeLeftovers :: !(IORef (Maybe ByteString)) } +-- | Make a 'Pipe' from a 'Handle' to read and a 'Handle' to write. +mkPipeFromHandles :: Handle -> Handle -> IO Pipe +mkPipeFromHandles pipeRead pipeWrite = do + let getSome = B.hGetSome pipeRead (32*1024) + putAll b = do + B.hPutBuilder pipeWrite b + hFlush pipeWrite + pipeLeftovers <- newIORef Nothing + pure $ Pipe { getSome, putAll, pipeLeftovers } + remoteCall :: Binary a => Pipe -> Message a -> IO a remoteCall pipe msg = do writePipe pipe (putMessage msg) readPipe pipe get +writePipe :: Pipe -> Put -> IO () +writePipe Pipe{..} put = putAll $ execPut put + remoteTHCall :: Binary a => Pipe -> THMessage a -> IO a remoteTHCall pipe msg = do writePipe pipe (putTHMessage msg) readPipe pipe get -writePipe :: Pipe -> Put -> IO () -writePipe Pipe{..} put - | LB.null bs = return () - | otherwise = do - LB.hPut pipeWrite bs - hFlush pipeWrite - where - bs = runPut put - readPipe :: Pipe -> Get a -> IO a readPipe Pipe{..} get = do leftovers <- readIORef pipeLeftovers - m <- getBin pipeRead get leftovers + m <- getBin getSome get leftovers case m of Nothing -> throw $ - mkIOError eofErrorType "GHCi.Message.remoteCall" (Just pipeRead) Nothing + mkIOError eofErrorType "GHCi.Message.readPipe" Nothing Nothing Just (result, new_leftovers) -> do writeIORef pipeLeftovers new_leftovers return result getBin - :: Handle -> Get a -> Maybe ByteString + :: (IO ByteString) -> Get a -> Maybe ByteString -> IO (Maybe (a, Maybe ByteString)) -getBin h get leftover = go leftover (runGetIncremental get) +getBin getsome get leftover = go leftover (runGetIncremental get) where go Nothing (Done leftover _ msg) = return (Just (msg, if B.null leftover then Nothing else Just leftover)) @@ -693,7 +699,7 @@ getBin h get leftover = go leftover (runGetIncremental get) go Nothing (fun (Just leftover)) go Nothing (Partial fun) = do -- putStrLn "before hGetSome" - b <- B.hGetSome h (32*1024) + b <- getsome -- putStrLn $ "hGetSome: " ++ show (B.length b) if B.null b then return Nothing diff --git a/libraries/ghci/GHCi/Server.hs b/libraries/ghci/GHCi/Server.hs index 69a5ea7b597aa910d02d46df999b89fc382f515f..c5c661da90acb25ed1202d7d8b25c763775a82cd 100644 --- a/libraries/ghci/GHCi/Server.hs +++ b/libraries/ghci/GHCi/Server.hs @@ -19,7 +19,6 @@ import Control.Exception import Control.Monad import Control.Concurrent (threadDelay) import Data.Binary -import Data.IORef import Text.Printf import System.Environment (getProgName, getArgs) @@ -127,8 +126,7 @@ defaultServer = do installSignalHandlers #endif - lo_ref <- newIORef Nothing - let pipe = Pipe{pipeRead = inh, pipeWrite = outh, pipeLeftovers = lo_ref} + pipe <- mkPipeFromHandles inh outh when wait $ do when verbose $