Fix race condition issues on Windows.

Former-commit-id: 970a6f8c92ba8cab41053cb7a933a45f416e8696
This commit is contained in:
David Himmelstrup 2019-09-12 14:54:59 +08:00
commit 158d79a9e7
6 changed files with 58 additions and 57 deletions

View file

@ -15,10 +15,10 @@ import Reanimate.Raster
import Codec.Picture import Codec.Picture
main :: IO () main :: IO ()
main = reanimate $ repeatAnimation 6 $ mkAnimation 5 $ do main = reanimate $ mkAnimation 5 $ do
s <- getSignal signalLinear s <- getSignal signalLinear
emit $ mkGroup emit $ mkGroup
[ mkBackground "black" [ mkBackground "grey"
, rotate (s*360) $ center $ scale 0.5 $ embedImage img ] , rotate (s*360) $ center $ scale 0.5 $ embedImage img ]
where where
img = generateImage pixelRenderer 255 255 img = generateImage pixelRenderer 255 255

View file

@ -67,7 +67,7 @@ library
diagrams-core, diagrams-lib, diagrams-contrib, diagrams-core, diagrams-lib, diagrams-contrib,
svg-builder, matrices, cubicbezier, palette, websockets, svg-builder, matrices, cubicbezier, palette, websockets,
hashable, fsnotify, open-browser, random-shuffle, base64-bytestring, hashable, fsnotify, open-browser, random-shuffle, base64-bytestring,
vector, colour, cassava, ansi-wl-pprint, here vector, colour, cassava, ansi-wl-pprint, here, temporary
Flag server Flag server
Description: Enable rendering server Description: Enable rendering server

View file

@ -3,7 +3,7 @@ module Reanimate.Driver ( reanimate ) where
import Control.Concurrent (MVar, forkIO, killThread, import Control.Concurrent (MVar, forkIO, killThread,
modifyMVar_, newEmptyMVar, modifyMVar_, newEmptyMVar,
putMVar, takeMVar) putMVar, takeMVar, forkOS)
import Control.Exception (SomeException, finally, handle) import Control.Exception (SomeException, finally, handle)
import Control.Monad import Control.Monad
import Control.Monad.Fix (fix) import Control.Monad.Fix (fix)
@ -13,8 +13,7 @@ import qualified Data.Text.Read as T
import Data.Version import Data.Version
import Network.WebSockets import Network.WebSockets
import Paths_reanimate import Paths_reanimate
import Reanimate.Misc (runCmdLazy, runCmd_, withTempDir, import Reanimate.Misc (runCmdLazy, runCmd_)
withTempFile)
import Reanimate.Monad (Animation) import Reanimate.Monad (Animation)
import Reanimate.Render (render, renderSnippets, import Reanimate.Render (render, renderSnippets,
renderSvgs) renderSvgs)
@ -24,8 +23,8 @@ import System.Environment (getArgs, getProgName)
import System.Exit import System.Exit
import System.FilePath import System.FilePath
import System.FSNotify import System.FSNotify
import System.IO (BufferMode (..), hPutStrLn, import System.IO.Temp
hSetBuffering, stderr, stdin) import System.IO
import Text.ParserCombinators.ReadP import Text.ParserCombinators.ReadP
import qualified Text.PrettyPrint.ANSI.Leijen as Doc import qualified Text.PrettyPrint.ANSI.Leijen as Doc
import Text.Printf import Text.Printf
@ -45,44 +44,48 @@ reanimate animation = do
["check"] -> checkEnvironment ["check"] -> checkEnvironment
["render", target] -> ["render", target] ->
render animation target render animation target
_ -> withTempDir $ \tmpDir -> do _ -> do
prog <- getProgName
lst <- listDirectory "."
mbSelf <- findFile ("." : lst) prog
case mbSelf of
Nothing -> do
hPutStrLn stderr "Failed to find own source code."
exitWith (ExitFailure 1)
Just self -> do
url <- getDataFileName "viewer/build/index.html" url <- getDataFileName "viewer/build/index.html"
putStrLn "Opening browser..." putStrLn "Opening browser..."
bSucc <- openBrowser url bSucc <- openBrowser url
if bSucc if bSucc
then putStrLn "Browser opened." then putStrLn "Browser opened."
else hPutStrLn stderr $ "Failed to open browser. Manually visit: " ++ url else hPutStrLn stderr $ "Failed to open browser. Manually visit: " ++ url
putStrLn "Listening..."
runServerWith "127.0.0.1" 9161 opts $ \pending -> do runServerWith "127.0.0.1" 9161 opts $ \pending -> do
putStrLn "Server pending..." putStrLn "New connection received."
prog <- getProgName
lst <- listDirectory "."
mbSelf <- findFile ("." : lst) prog
blocker <- newEmptyMVar :: IO (MVar ())
case mbSelf of
Nothing -> do
hPutStrLn stderr "Failed to find own source code."
Just self -> do
conn <- acceptRequest pending conn <- acceptRequest pending
slave <- newEmptyMVar slave <- newEmptyMVar
let handler = modifyMVar_ slave $ \tid -> do let handler = modifyMVar_ slave $ \tid -> do
sendTextData conn (T.pack "Compiling")
putStrLn "Killing and respawning..." putStrLn "Reloading code..."
killThread tid killThread tid
tid <- forkIO $ slaveHandler conn self tmpDir tid <- forkOS $ slaveHandler conn self
return tid return tid
killSlave = do killSlave = do
tid <- takeMVar slave tid <- takeMVar slave
killThread tid killThread tid
putStrLn "Found self. Listening..."
stop <- watchFile watch self handler stop <- watchFile watch self handler
putMVar slave =<< forkIO (return ()) putMVar slave =<< forkIO (return ())
let loop = do let loop = do
fps <- receiveData conn :: IO T.Text fps <- receiveData conn :: IO T.Text
handler handler
loop loop
loop `finally` (killSlave >> stop) loop `finally` (stop >> killSlave)
slaveHandler conn self tmpDir = withTempFile ".exe" $ \tmpExecutable -> do slaveHandler conn self =
withSystemTempDirectory "reanimate" $ \tmpDir ->
withTempFile tmpDir "reanimate.exe" $ \tmpExecutable handle -> do
hClose handle
sendTextData conn (T.pack "Compiling")
ret <- runCmd_ "stack" $ ["ghc", "--"] ++ ghcOptions tmpDir ++ [self, "-o", tmpExecutable] ret <- runCmd_ "stack" $ ["ghc", "--"] ++ ghcOptions tmpDir ++ [self, "-o", tmpExecutable]
case ret of case ret of
Left err -> Left err ->
@ -90,7 +93,6 @@ slaveHandler conn self tmpDir = withTempFile ".exe" $ \tmpExecutable -> do
Right{} -> do Right{} -> do
getFrame <- runCmdLazy tmpExecutable ["once", "+RTS", "-N", "-M1G", "-RTS"] getFrame <- runCmdLazy tmpExecutable ["once", "+RTS", "-N", "-M1G", "-RTS"]
(frameCount,_) <- expectFrame =<< getFrame (frameCount,_) <- expectFrame =<< getFrame
-- sendTextData conn (T.pack "Compiled")
sendTextData conn (T.pack $ show frameCount) sendTextData conn (T.pack $ show frameCount)
fix $ \loop -> do fix $ \loop -> do
(frameIdx, frame) <- expectFrame =<< getFrame (frameIdx, frame) <- expectFrame =<< getFrame
@ -213,14 +215,13 @@ ffmpegVersion = do
hasTeXPackage :: FilePath -> String -> IO (Either String String) hasTeXPackage :: FilePath -> String -> IO (Either String String)
hasTeXPackage exec pkg = handle (\(e::SomeException) -> return $ Left "n/a") $ hasTeXPackage exec pkg = handle (\(e::SomeException) -> return $ Left "n/a") $
withTempDir $ \tmp_dir -> withTempFile "tex" $ \tex_file -> do withSystemTempDirectory "reanimate" $ \tmp_dir -> withTempFile tmp_dir "test.tex" $ \tex_file tex_handle -> do
let tmp_dir = "." hPutStr tex_handle tex_document
tex_file = "test.tex" hPutStr tex_handle $ "\\usepackage" ++ pkg ++ "\n"
writeFile tex_file tex_document hPutStr tex_handle "\\begin{document}\n"
appendFile tex_file $ "\\usepackage" ++ pkg ++ "\n" hPutStr tex_handle "blah\n"
appendFile tex_file "\\begin{document}\n" hPutStr tex_handle tex_epilogue
appendFile tex_file "blah\n" hClose tex_handle
appendFile tex_file tex_epilogue
ret <- runCmd_ exec ["-interaction=batchmode", "-halt-on-error", "-output-directory="++tmp_dir, tex_file] ret <- runCmd_ exec ["-interaction=batchmode", "-halt-on-error", "-output-directory="++tmp_dir, tex_file]
return $ case ret of return $ case ret of
Right{} -> Right "OK" Right{} -> Right "OK"

View file

@ -69,7 +69,7 @@ runCmdLazy exec args = do
withTempDir :: (FilePath -> IO a) -> IO a withTempDir :: (FilePath -> IO a) -> IO a
withTempDir action = do withTempDir action = do
dir <- getTemporaryDirectory dir <- getTemporaryDirectory
(path, handle) <- openTempFile dir "reanimate-XXXXXX" (path, handle) <- openTempFile dir "reanimate"
hClose handle hClose handle
removeFile path removeFile path
createDirectory (dir </> path) createDirectory (dir </> path)
@ -78,6 +78,6 @@ withTempDir action = do
withTempFile :: String -> (FilePath -> IO a) -> IO a withTempFile :: String -> (FilePath -> IO a) -> IO a
withTempFile ext action = do withTempFile ext action = do
dir <- getTemporaryDirectory dir <- getTemporaryDirectory
(path, handle) <- openTempFile dir ("reanimate-XXXXXX" <.> ext) (path, handle) <- openTempFile dir ("reanimate" <.> ext)
hClose handle hClose handle
action path -- `finally` removeFile path action path -- `finally` removeFile path

View file

@ -1,4 +1,4 @@
resolver: lts-13.14 resolver: lts-11.14
allow-newer: false allow-newer: false