write pid file even when running in foreground

This prevents multiple runs of the assistant in the foreground, and lets
--stop stop foregrounded runs too.

The webapp firstrun case also now writes a pid file, once it's made the git
repo to put it in.
This commit is contained in:
Joey Hess 2012-08-01 16:29:38 -04:00
parent ecc168aba3
commit 8181b38ef6
3 changed files with 15 additions and 10 deletions

View file

@ -129,6 +129,7 @@ startDaemon :: Bool -> Bool -> Maybe (Url -> FilePath -> IO ()) -> Annex ()
startDaemon assistant foreground webappwaiter startDaemon assistant foreground webappwaiter
| foreground = do | foreground = do
showStart (if assistant then "assistant" else "watch") "." showStart (if assistant then "assistant" else "watch") "."
liftIO . Utility.Daemon.lockPidFile =<< fromRepo gitAnnexPidFile
go id go id
| otherwise = do | otherwise = do
logfd <- liftIO . openLog =<< fromRepo gitAnnexLogFile logfd <- liftIO . openLog =<< fromRepo gitAnnexLogFile

View file

@ -14,7 +14,7 @@ import Assistant.DaemonStatus
import Assistant.TransferQueue import Assistant.TransferQueue
import Assistant.Threads.WebApp import Assistant.Threads.WebApp
import Utility.WebApp import Utility.WebApp
import Utility.Daemon (checkDaemon) import Utility.Daemon (checkDaemon, lockPidFile)
import Init import Init
import qualified Command.Watch import qualified Command.Watch
import qualified Git.CurrentRepo import qualified Git.CurrentRepo
@ -94,6 +94,10 @@ firstRun = do
_wait <- takeMVar v _wait <- takeMVar v
state <- Annex.new =<< Git.CurrentRepo.get state <- Annex.new =<< Git.CurrentRepo.get
Annex.eval state $ Annex.eval state $ do
dummydaemonize
startAssistant True id $ Just $ sendurlback v startAssistant True id $ Just $ sendurlback v
sendurlback v url _htmlshim = putMVar v url sendurlback v url _htmlshim = putMVar v url
{- Set up the pid file in the new repo. -}
dummydaemonize = do
liftIO . lockPidFile =<< fromRepo gitAnnexPidFile

View file

@ -27,7 +27,7 @@ daemonize logfd pidfile changedirectory a = do
_ <- forkProcess child2 _ <- forkProcess child2
out out
child2 = do child2 = do
maybe noop (lockPidFile alreadyrunning) pidfile maybe noop lockPidFile pidfile
when changedirectory $ when changedirectory $
setCurrentDirectory "/" setCurrentDirectory "/"
nullfd <- openFd "/dev/null" ReadOnly Nothing defaultFileFlags nullfd <- openFd "/dev/null" ReadOnly Nothing defaultFileFlags
@ -39,28 +39,28 @@ daemonize logfd pidfile changedirectory a = do
redir newh h = do redir newh h = do
closeFd h closeFd h
dupTo newh h dupTo newh h
alreadyrunning = error "Daemon is already running."
out = exitImmediately ExitSuccess out = exitImmediately ExitSuccess
{- Locks the pid file, with an exclusive, non-blocking lock. {- Locks the pid file, with an exclusive, non-blocking lock.
- Runs an action on failure. On success, writes the pid to the file, - Writes the pid to the file, fully atomically.
- fully atomically. -} - Fails if the pid file is already locked by another process. -}
lockPidFile :: IO () -> FilePath -> IO () lockPidFile :: FilePath -> IO ()
lockPidFile onfailure file = do lockPidFile file = do
fd <- openFd file ReadWrite (Just stdFileMode) defaultFileFlags fd <- openFd file ReadWrite (Just stdFileMode) defaultFileFlags
locked <- catchMaybeIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0) locked <- catchMaybeIO $ setLock fd (WriteLock, AbsoluteSeek, 0, 0)
fd' <- openFd newfile ReadWrite (Just stdFileMode) defaultFileFlags fd' <- openFd newfile ReadWrite (Just stdFileMode) defaultFileFlags
{ trunc = True } { trunc = True }
locked' <- catchMaybeIO $ setLock fd' (WriteLock, AbsoluteSeek, 0, 0) locked' <- catchMaybeIO $ setLock fd' (WriteLock, AbsoluteSeek, 0, 0)
case (locked, locked') of case (locked, locked') of
(Nothing, _) -> onfailure (Nothing, _) -> alreadyrunning
(_, Nothing) -> onfailure (_, Nothing) -> alreadyrunning
_ -> do _ -> do
_ <- fdWrite fd' =<< show <$> getProcessID _ <- fdWrite fd' =<< show <$> getProcessID
renameFile newfile file renameFile newfile file
closeFd fd closeFd fd
where where
newfile = file ++ ".new" newfile = file ++ ".new"
alreadyrunning = error "Daemon is already running."
{- Checks if the daemon is running, by checking that the pid file {- Checks if the daemon is running, by checking that the pid file
- is locked by the same process that is listed in the pid file. - is locked by the same process that is listed in the pid file.