This reverts commit ef0e3ac22e.
Sebastian thinks best to revert this:
It seems to me the reason I needed to look at activatable sockets
might actually be a networkd bug, and I was in error about patch 0001.
On my machines (without DHCP), networkd quits after configuring the
links. I thought this had to do with network activation, but that was
probably mistaken. This was obscured by my testing the change by doing
systemctl stop/start on networkd; now that I actually unplugged the
network cable, I noticed no DBus messages are triggered by this on
this machine. Your test case might have had a similar problem
(networkd quitting on idle). Might be related to [1].
On another machine (with DHCP) networkd remains active all the time,
and patch 0002 works there. You might want to revert 0001, though:
Suppose someone’s running no manager at all, so that polling would be
required. Because networkd is still listed as activable, we would
refrain from polling – by mistake, because networkd doesn’t seem to
actually go active if we listen on its bus, and it’s listed as
activable even when it’s not configured. Connectivity-related messages
will come in when stopping/starting the service, but not when
unplugging the cable.
		
	
			
		
			
				
	
	
		
			85 lines
		
	
	
	
		
			2.8 KiB
			
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
	
		
			2.8 KiB
			
		
	
	
	
		
			Haskell
		
	
	
	
	
	
{- DBus utilities
 | 
						|
 -
 | 
						|
 - Copyright 2012 Joey Hess <id@joeyh.name>
 | 
						|
 -
 | 
						|
 - License: BSD-2-clause
 | 
						|
 -}
 | 
						|
 | 
						|
{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}
 | 
						|
 | 
						|
module Utility.DBus where
 | 
						|
 | 
						|
import Utility.PartialPrelude
 | 
						|
import Utility.Exception
 | 
						|
 | 
						|
import DBus.Client
 | 
						|
import DBus
 | 
						|
import Data.Maybe
 | 
						|
import Control.Concurrent
 | 
						|
import Control.Exception as E
 | 
						|
 | 
						|
type ServiceName = String
 | 
						|
 | 
						|
listServiceNames :: Client -> IO [ServiceName]
 | 
						|
listServiceNames client = do
 | 
						|
	reply <- callDBus client "ListNames" []
 | 
						|
	return $ fromMaybe [] $ fromVariant =<< headMaybe (methodReturnBody reply)
 | 
						|
 | 
						|
callDBus :: Client -> MemberName -> [Variant] -> IO MethodReturn
 | 
						|
callDBus client name params = call_ client $
 | 
						|
	(methodCall "/org/freedesktop/DBus" "org.freedesktop.DBus" name)
 | 
						|
		{ methodCallDestination = Just "org.freedesktop.DBus"
 | 
						|
		, methodCallBody = params
 | 
						|
		}
 | 
						|
 | 
						|
{- Connects to the bus, and runs the client action.
 | 
						|
 - 
 | 
						|
 - Throws a ClientError, and closes the connection if it fails to
 | 
						|
 - process an incoming message, or if the connection is lost.
 | 
						|
 - Unlike DBus's usual interface, this error is thrown at the top level,
 | 
						|
 - rather than inside the clientThreadRunner, so it can be caught, and
 | 
						|
 - runClient re-run as needed. -}
 | 
						|
runClient :: IO (Maybe Address) -> (Client -> IO ()) -> IO ()
 | 
						|
runClient getaddr clientaction = do
 | 
						|
	env <- getaddr
 | 
						|
	case env of
 | 
						|
		Nothing -> throwIO (clientError "runClient: unable to determine DBUS address")
 | 
						|
		Just addr -> do
 | 
						|
			{- The clientaction will set up listeners, which
 | 
						|
			 - run in a different thread. We block while
 | 
						|
			 - they're running, until our threadrunner catches
 | 
						|
			 - a ClientError, which it will put into the MVar
 | 
						|
			 - to be rethrown here. -}
 | 
						|
			mv <- newEmptyMVar
 | 
						|
			let tr = threadrunner (putMVar mv)
 | 
						|
			let opts = defaultClientOptions { clientThreadRunner = tr }
 | 
						|
			client <- connectWith opts addr
 | 
						|
			clientaction client
 | 
						|
			e <- takeMVar mv
 | 
						|
			disconnect client
 | 
						|
			throw e
 | 
						|
  where
 | 
						|
	threadrunner storeerr io = loop
 | 
						|
	  where
 | 
						|
		loop = catchClientError (io >> loop) storeerr
 | 
						|
 | 
						|
{- Connects to the bus, and runs the client action.
 | 
						|
 -
 | 
						|
 - 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
 | 
						|
 - exponential backoff). Once onretry returns, the connection is retried.
 | 
						|
 -}
 | 
						|
persistentClient :: IO (Maybe Address) -> v -> (SomeException -> v -> IO v) -> (Client -> IO ()) -> IO ()
 | 
						|
persistentClient getaddr v onretry clientaction =
 | 
						|
	{- runClient can fail with not just ClientError, but also other
 | 
						|
	 - things, if dbus is not running. Let async exceptions through. -}
 | 
						|
	runClient getaddr clientaction `catchNonAsync` retry
 | 
						|
  where
 | 
						|
	retry e = do
 | 
						|
		v' <- onretry e v
 | 
						|
		persistentClient getaddr v' onretry clientaction
 | 
						|
 | 
						|
{- Catches only ClientError -}
 | 
						|
catchClientError :: IO () -> (ClientError -> IO ()) -> IO ()
 | 
						|
catchClientError io handler =
 | 
						|
	either handler return =<< (E.try io :: IO (Either ClientError ()))
 |