NetWatcher: When dbus connection is lost, try to reconnect.

MountWatcher can't do this, because it uses the session dbus,
and won't have access to the new DBUS_SESSION_BUS_ADDRESS if a new session
is started.

Bumped dbus library version, FD leak in it is fixed.
This commit is contained in:
Joey Hess 2012-10-26 19:38:27 -04:00
parent 87c250da5b
commit 8e4620a6c7
6 changed files with 25 additions and 18 deletions

View file

@ -72,6 +72,11 @@ dbusThread st dstatus scanremotes = E.catch (runClient getSessionAddress go) one
) )
onerr :: E.SomeException -> IO () onerr :: E.SomeException -> IO ()
onerr e = do onerr e = do
{- If the session dbus fails, the user probably
- logged out of their desktop. Even if they log
- back in, we won't have access to the dbus
- session key, so polling is the best that can be
- done in this situation. -}
runThreadState st $ runThreadState st $
warning $ "dbus failed; falling back to mtab polling (" ++ show e ++ ")" warning $ "dbus failed; falling back to mtab polling (" ++ show e ++ ")"
pollinstead pollinstead

View file

@ -24,7 +24,6 @@ import Utility.DBus
import DBus.Client import DBus.Client
import DBus import DBus
import Data.Word (Word32) import Data.Word (Word32)
import qualified Control.Exception as E
#else #else
#warning Building without dbus support; will poll for network connection changes #warning Building without dbus support; will poll for network connection changes
#endif #endif
@ -57,22 +56,24 @@ netWatcherFallbackThread st dstatus scanremotes = thread $
#if WITH_DBUS #if WITH_DBUS
dbusThread :: ThreadState -> DaemonStatusHandle -> ScanRemoteMap -> IO () dbusThread :: ThreadState -> DaemonStatusHandle -> ScanRemoteMap -> IO ()
dbusThread st dstatus scanremotes = E.catch (runClient getSystemAddress go) onerr dbusThread st dstatus scanremotes = persistentClient getSystemAddress () onerr go
where where
go client = ifM (checkNetMonitor client) go client = ifM (checkNetMonitor client)
( do ( do
listenNMConnections client handle listenNMConnections client handleconn
listenWicdConnections client handle listenWicdConnections client handleconn
, do , do
runThreadState st $ runThreadState st $
warning "No known network monitor available through dbus; falling back to polling" warning "No known network monitor available through dbus; falling back to polling"
) )
onerr :: E.SomeException -> IO () handleconn = do
onerr e = runThreadState st $
warning $ "dbus failed; falling back to polling (" ++ show e ++ ")"
handle = do
debug thisThread ["detected network connection"] debug thisThread ["detected network connection"]
handleConnection st dstatus scanremotes handleConnection st dstatus scanremotes
onerr e _ = do
runThreadState st $
warning $ "lost dbus connection; falling back to polling (" ++ show e ++ ")"
{- Wait, in hope that dbus will come back -}
threadDelaySeconds (Seconds 60)
{- Examine the list of services connected to dbus, to see if there {- Examine the list of services connected to dbus, to see if there
- are any we can use to monitor network connections. -} - are any we can use to monitor network connections. -}

View file

@ -5,7 +5,7 @@
- Licensed under the GNU GPL version 3 or higher. - Licensed under the GNU GPL version 3 or higher.
-} -}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
module Utility.DBus where module Utility.DBus where
@ -65,15 +65,15 @@ runClient getaddr clientaction = do
- If the connection is lost, runs onretry, which can do something like - If the connection is lost, runs onretry, which can do something like
- a delay, or printing a warning, and has a state value (useful for - a delay, or printing a warning, and has a state value (useful for
- exponential backoff). Once onretry returns, the connection is retried. - exponential backoff). Once onretry returns, the connection is retried.
- -}
- Warning: Currently connectWith can throw a SocketError and leave behind
- an open FD. So each retry leaks one FD. -}
persistentClient :: IO (Maybe Address) -> v -> (SomeException -> v -> IO v) -> (Client -> IO ()) -> IO () persistentClient :: IO (Maybe Address) -> v -> (SomeException -> v -> IO v) -> (Client -> IO ()) -> IO ()
persistentClient getaddr v onretry clientaction = do persistentClient getaddr v onretry clientaction =
{- runClient can fail with not just ClientError, but also other {- runClient can fail with not just ClientError, but also other
- things, if dbus is not running. -} - things, if dbus is not running. Let async exceptions through. -}
r <- E.try (runClient getaddr clientaction) :: IO (Either SomeException ()) runClient getaddr clientaction `E.catches`
either retry return r [ Handler (\ (e :: AsyncException) -> E.throw e)
, Handler (\ (e :: SomeException) -> retry e)
]
where where
retry e = do retry e = do
v' <- onretry e v v' <- onretry e v

1
debian/changelog vendored
View file

@ -24,6 +24,7 @@ git-annex (3.20121018) UNRELEASED; urgency=low
* configure: Check that checksum programs produce correct checksums. * configure: Check that checksum programs produce correct checksums.
* Re-enable dbus, using a new version of the library that fixes the memory * Re-enable dbus, using a new version of the library that fixes the memory
leak. leak.
* NetWatcher: When dbus connection is lost, try to reconnect.
* Use USER and HOME environment when set, and only fall back to getpwent, * Use USER and HOME environment when set, and only fall back to getpwent,
which doesn't work with LDAP or NIS. which doesn't work with LDAP or NIS.

2
debian/control vendored
View file

@ -22,7 +22,7 @@ Build-Depends:
libghc-edit-distance-dev, libghc-edit-distance-dev,
libghc-hinotify-dev [linux-any], libghc-hinotify-dev [linux-any],
libghc-stm-dev (>= 2.3), libghc-stm-dev (>= 2.3),
libghc-dbus-dev [linux-any] (>= 0.10.2), libghc-dbus-dev [linux-any] (>= 0.10.3),
libghc-yesod-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64], libghc-yesod-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64],
libghc-yesod-static-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64], libghc-yesod-static-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64],
libghc-yesod-default-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64], libghc-yesod-default-dev [i386 amd64 kfreebsd-i386 kfreebsd-amd64],

View file

@ -77,7 +77,7 @@ Executable git-annex
C-Sources: Utility/libkqueue.c C-Sources: Utility/libkqueue.c
if os(linux) && flag(Dbus) if os(linux) && flag(Dbus)
Build-Depends: dbus (>= 0.10.2) Build-Depends: dbus (>= 0.10.3)
CPP-Options: -DWITH_DBUS CPP-Options: -DWITH_DBUS
if flag(Webapp) && flag(Assistant) if flag(Webapp) && flag(Assistant)