more OsPath conversion (542/749)
Sponsored-by: Luke T. Shumaker
This commit is contained in:
parent
0d2b805806
commit
0811531b59
13 changed files with 127 additions and 116 deletions
|
@ -5,6 +5,7 @@
|
|||
- License: BSD-2-clause
|
||||
-}
|
||||
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE CPP #-}
|
||||
|
||||
module Utility.Daemon (
|
||||
|
@ -25,6 +26,7 @@ import Utility.OpenFd
|
|||
#else
|
||||
import System.Win32.Process (terminateProcessById)
|
||||
import Utility.LockFile
|
||||
import qualified Utility.OsString as OS
|
||||
#endif
|
||||
|
||||
#ifndef mingw32_HOST_OS
|
||||
|
@ -42,7 +44,7 @@ import System.Posix hiding (getEnv, getEnvironment)
|
|||
- Instead, it runs the cmd with provided params, in the background,
|
||||
- which the caller should arrange to run this again.
|
||||
-}
|
||||
daemonize :: String -> [CommandParam] -> IO Fd -> Maybe FilePath -> Bool -> IO () -> IO ()
|
||||
daemonize :: String -> [CommandParam] -> IO Fd -> Maybe OsPath -> Bool -> IO () -> IO ()
|
||||
daemonize cmd params openlogfd pidfile changedirectory a = do
|
||||
maybe noop checkalreadyrunning pidfile
|
||||
getEnv envvar >>= \case
|
||||
|
@ -70,10 +72,10 @@ daemonize cmd params openlogfd pidfile changedirectory a = do
|
|||
|
||||
{- To run an action that is normally daemonized in the foreground. -}
|
||||
#ifndef mingw32_HOST_OS
|
||||
foreground :: IO Fd -> Maybe FilePath -> IO () -> IO ()
|
||||
foreground :: IO Fd -> Maybe OsPath -> IO () -> IO ()
|
||||
foreground openlogfd pidfile a = do
|
||||
#else
|
||||
foreground :: Maybe FilePath -> IO () -> IO ()
|
||||
foreground :: Maybe OsPath -> IO () -> IO ()
|
||||
foreground pidfile a = do
|
||||
#endif
|
||||
maybe noop lockPidFile pidfile
|
||||
|
@ -93,12 +95,12 @@ foreground pidfile a = do
|
|||
-
|
||||
- Writes the pid to the file, fully atomically.
|
||||
- Fails if the pid file is already locked by another process. -}
|
||||
lockPidFile :: FilePath -> IO ()
|
||||
lockPidFile :: OsPath -> IO ()
|
||||
lockPidFile pidfile = do
|
||||
#ifndef mingw32_HOST_OS
|
||||
fd <- openFdWithMode (toRawFilePath pidfile) ReadWrite (Just stdFileMode) defaultFileFlags
|
||||
fd <- openFdWithMode (fromOsPath pidfile) ReadWrite (Just stdFileMode) defaultFileFlags
|
||||
locked <- catchMaybeIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
|
||||
fd' <- openFdWithMode (toRawFilePath newfile) ReadWrite (Just stdFileMode) defaultFileFlags
|
||||
fd' <- openFdWithMode (fromOsPath newfile) ReadWrite (Just stdFileMode) defaultFileFlags
|
||||
{ trunc = True }
|
||||
locked' <- catchMaybeIO $ setLock fd' (WriteLock, AbsoluteSeek, 0, 0)
|
||||
case (locked, locked') of
|
||||
|
@ -107,17 +109,17 @@ lockPidFile pidfile = do
|
|||
_ -> do
|
||||
_ <- fdWrite fd' =<< show <$> getPID
|
||||
closeFd fd
|
||||
rename newfile pidfile
|
||||
renameFile newfile pidfile
|
||||
where
|
||||
newfile = pidfile ++ ".new"
|
||||
newfile = pidfile <> literalOsPath ".new"
|
||||
#else
|
||||
{- Not atomic on Windows, oh well. -}
|
||||
unlessM (isNothing <$> checkDaemon pidfile)
|
||||
alreadyRunning
|
||||
pid <- getPID
|
||||
writeFile pidfile (show pid)
|
||||
writeFile (fromOsPath pidfile) (show pid)
|
||||
lckfile <- winLockFile pid pidfile
|
||||
writeFile (fromRawFilePath lckfile) ""
|
||||
writeFile (fromOsPath lckfile) ""
|
||||
void $ lockExclusive lckfile
|
||||
#endif
|
||||
|
||||
|
@ -128,17 +130,17 @@ alreadyRunning = giveup "Daemon is already running."
|
|||
- is locked by the same process that is listed in the pid file.
|
||||
-
|
||||
- If it's running, returns its pid. -}
|
||||
checkDaemon :: FilePath -> IO (Maybe PID)
|
||||
checkDaemon :: OsPath -> IO (Maybe PID)
|
||||
#ifndef mingw32_HOST_OS
|
||||
checkDaemon pidfile = bracket setup cleanup go
|
||||
where
|
||||
setup = catchMaybeIO $
|
||||
openFdWithMode (toRawFilePath pidfile) ReadOnly (Just stdFileMode) defaultFileFlags
|
||||
openFdWithMode (fromOsPath pidfile) ReadOnly (Just stdFileMode) defaultFileFlags
|
||||
cleanup (Just fd) = closeFd fd
|
||||
cleanup Nothing = return ()
|
||||
go (Just fd) = catchDefaultIO Nothing $ do
|
||||
locked <- getLock fd (ReadLock, AbsoluteSeek, 0, 0)
|
||||
p <- readish <$> readFile pidfile
|
||||
p <- readish <$> readFile (fromOsPath pidfile)
|
||||
return (check locked p)
|
||||
go Nothing = return Nothing
|
||||
|
||||
|
@ -147,16 +149,16 @@ checkDaemon pidfile = bracket setup cleanup go
|
|||
check (Just (pid, _)) (Just pid')
|
||||
| pid == pid' = Just pid
|
||||
| otherwise = giveup $
|
||||
"stale pid in " ++ pidfile ++
|
||||
"stale pid in " ++ fromOsPath pidfile ++
|
||||
" (got " ++ show pid' ++
|
||||
"; expected " ++ show pid ++ " )"
|
||||
#else
|
||||
checkDaemon pidfile = maybe (return Nothing) (check . readish)
|
||||
=<< catchMaybeIO (readFile pidfile)
|
||||
=<< catchMaybeIO (readFile (fromOsPath pidfile))
|
||||
where
|
||||
check Nothing = return Nothing
|
||||
check (Just pid) = do
|
||||
v <- lockShared =<< winLockFile pid pidfile
|
||||
v <- lockShared =<< winLockFile pid (fromOsPath pidfile)
|
||||
case v of
|
||||
Just h -> do
|
||||
dropLock h
|
||||
|
@ -165,7 +167,7 @@ checkDaemon pidfile = maybe (return Nothing) (check . readish)
|
|||
#endif
|
||||
|
||||
{- Stops the daemon, safely. -}
|
||||
stopDaemon :: FilePath -> IO ()
|
||||
stopDaemon :: OsPath -> IO ()
|
||||
stopDaemon pidfile = go =<< checkDaemon pidfile
|
||||
where
|
||||
go Nothing = noop
|
||||
|
@ -181,14 +183,14 @@ stopDaemon pidfile = go =<< checkDaemon pidfile
|
|||
- when eg, restarting the daemon.
|
||||
-}
|
||||
#ifdef mingw32_HOST_OS
|
||||
winLockFile :: PID -> FilePath -> IO RawFilePath
|
||||
winLockFile :: PID -> OsPath -> IO OsPath
|
||||
winLockFile pid pidfile = do
|
||||
cleanstale
|
||||
return $ toRawFilePath $ prefix ++ show pid ++ suffix
|
||||
return $ prefix <> toOsPath (show pid) <> suffix
|
||||
where
|
||||
prefix = pidfile ++ "."
|
||||
suffix = ".lck"
|
||||
prefix = pidfile <> literalOsPath "."
|
||||
suffix = literalOsPath ".lck"
|
||||
cleanstale = mapM_ (void . tryIO . removeFile) =<<
|
||||
(filter iswinlockfile . map fromRawFilePath <$> dirContents (parentDir (toRawFilePath pidfile)))
|
||||
iswinlockfile f = suffix `isSuffixOf` f && prefix `isPrefixOf` f
|
||||
(filter iswinlockfile <$> dirContents (parentDir pidfile))
|
||||
iswinlockfile f = suffix `OS.isSuffixOf` f && prefix `OS.isPrefixOf` f
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue