selfrestart (empty) → 0.1.0
raw patch · 3 files changed
+100/−0 lines, 3 filesdep +basedep +directorydep +executable-pathsetup-changed
Dependencies added: base, directory, executable-path, unix
Files
- Setup.hs +2/−0
- System/SelfRestart.hs +73/−0
- selfrestart.cabal +25/−0
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ System/SelfRestart.hs view
@@ -0,0 +1,73 @@+-- | Allows restarting the currently running executable.+--+-- Works with binaries and `runhaskell`/`runghc`. In `ghci` all functions are no-ops.+module System.SelfRestart+ ( -- $usewithcare+ selfRestart+ , forkSelfRestartExePoll+ , forkSelfRestartExePollWithAction+ ) where++import Control.Applicative+import Control.Concurrent+import Control.Monad+import System.Posix.Process (executeFile)+import System.Directory (getModificationTime)+import System.Environment.Executable (getExecutablePath, getScriptPath, ScriptPath (..))+import GHC.Environment (getFullArgs)++-- $usewithcare+-- USE WITH CARE. This module uses `getScriptPath` internally, which is /experimental/.+-- Please review it.++-- | Restart the currently running executable.+selfRestart :: IO ()+selfRestart = do+ realExePath <- getExecutablePath+ scriptPath <- getScriptPath+ fullArgs <- getFullArgs++ case scriptPath of+ Executable p -> restart p fullArgs+ RunGHC _ -> restart realExePath fullArgs+ Interactive -> return ()++ where+ restart exePath args = executeFile exePath False args Nothing+++-- | Forks a thread to check poll the own binary's modification time every,+-- and restarts, and restarts it when it gets changed.+--+-- Waits the given number of seconds between checks.+forkSelfRestartExePoll :: Double -> IO (Maybe ThreadId)+forkSelfRestartExePoll pollSeconds = forkSelfRestartExePollWithAction pollSeconds (return ())+++-- | Like `forkSelfRestartExePoll`, but you can run an action just before the restart+-- happens.+forkSelfRestartExePollWithAction :: Double -> IO () -> IO (Maybe ThreadId)+forkSelfRestartExePollWithAction pollSeconds shutdownAction = do+ when (pollTimeoutUs < 0) $ error $ "forkSelfRestartExePollWithAction: Bad poll timeout: " ++ show pollSeconds++ realExePath <- getExecutablePath+ scriptPath <- getScriptPath+ fullArgs <- getFullArgs++ case scriptPath of+ Executable p -> Just <$> spawn p p fullArgs+ RunGHC p -> Just <$> spawn p realExePath fullArgs+ Interactive -> return Nothing++ where+ pollTimeoutUs = floor $ pollSeconds * 1000000++ spawn watchPath exePath args = do+ mtimeStarted <- getModificationTime watchPath+ forkIO $+ forever $ do+ threadDelay pollTimeoutUs+ mtime <- getModificationTime watchPath+ when (mtime > mtimeStarted) $ do+ shutdownAction+ executeFile exePath False args Nothing
+ selfrestart.cabal view
@@ -0,0 +1,25 @@+name: selfrestart+version: 0.1.0+license: MIT+author: Niklas Hambüchen <mail@nh2.me>+maintainer: Niklas Hambüchen <mail@nh2.me>+build-type: Simple+cabal-version: >=1.8+homepage: https://github.com/nh2/selfrestart+bug-reports: https://github.com/nh2/selfrestart/issues+synopsis: Restarts the current executable (on binary change)+description:+ Allows restarting the currently running executable.+ .+ Can restart the running program binary using @exec()@,+ either manually or when the binary changes.+ .+ Also works with runhaskell/runghc.+++library+ exposed-modules: System.SelfRestart+ build-depends: base >= 4.5 && < 5+ , directory >= 1.2+ , executable-path >= 0.0.3+ , unix >= 2.6