def __init__(self, interface): self.interface = interface self.interface._impl = self App.app = self # Add a reference for the PythonAppDelegate class to use. asyncio.set_event_loop_policy(EventLoopPolicy()) self.loop = asyncio.get_event_loop()
def __init__(self, interface): self.interface = interface self.interface._impl = self self._cursor_visible = True asyncio.set_event_loop_policy(EventLoopPolicy()) self.loop = asyncio.get_event_loop()
def setUp(self): asyncio.set_event_loop_policy(EventLoopPolicy()) self.loop = asyncio.get_event_loop()
def PasteboardWriter(): global loop asyncio.set_event_loop_policy(EventLoopPolicy()) loop = asyncio.get_event_loop() loop.add_reader(sys.stdin.fileno(), read_input) loop.run_forever()
def __init__(self, interface): self.interface = interface self.interface._impl = self asyncio.set_event_loop_policy(EventLoopPolicy()) self.loop = asyncio.get_event_loop()
def start_maestral_daemon(config_name: str = "maestral", log_to_stderr: bool = False, start_sync: bool = False) -> None: """ Starts the Maestral daemon with event loop in the current thread. Startup is race free: there will never be more than one daemon running with the same config name. The daemon is a :class:`maestral.main.Maestral` instance which is exposed as Pyro daemon object and listens for requests on a unix domain socket. This call starts an asyncio event loop to process client requests and blocks until the event loop shuts down. On macOS, the event loop is integrated with Cocoa's CFRunLoop. This allows processing Cocoa events and callbacks, for instance for desktop notifications. :param config_name: The name of the Maestral configuration to use. :param log_to_stderr: If ``True``, write logs to stderr. :param start_sync: If ``True``, start syncing once the daemon has started. If the ``start_sync`` call fails, an error will be logged but not raised. :raises RuntimeError: if a daemon for the given ``config_name`` is already running. """ import asyncio from .main import Maestral from .logging import scoped_logger, setup_logging setup_logging(config_name, log_to_stderr) dlogger = scoped_logger(__name__, config_name) dlogger.info("Starting daemon") if threading.current_thread() is not threading.main_thread(): dlogger.error("Must run daemon in main thread") raise RuntimeError("Must run daemon in main thread") dlogger.debug("Environment:\n%s", pformat(os.environ.copy())) # acquire PID lock file lock = maestral_lock(config_name) if lock.acquire(): dlogger.debug("Acquired daemon lock: %s", lock.path) else: dlogger.error("Could not acquire lock, daemon is already running") raise RuntimeError("Daemon is already running") # Nice ourselves to give other processes priority. os.nice(10) # Integrate with CFRunLoop in macOS. if IS_MACOS: dlogger.debug("Integrating with CFEventLoop") from rubicon.objc.eventloop import EventLoopPolicy # type: ignore asyncio.set_event_loop_policy(EventLoopPolicy()) # Get the default event loop. loop = asyncio.get_event_loop() sd_notifier = sdnotify.SystemdNotifier() # Notify systemd that we have started. if NOTIFY_SOCKET: dlogger.debug("Running as systemd notify service") dlogger.debug("NOTIFY_SOCKET = %s", NOTIFY_SOCKET) sd_notifier.notify("READY=1") # Notify systemd periodically if alive. if IS_WATCHDOG and WATCHDOG_USEC: async def periodic_watchdog() -> None: if WATCHDOG_USEC: sleep = int(WATCHDOG_USEC) while True: sd_notifier.notify("WATCHDOG=1") await asyncio.sleep(sleep / (2 * 10**6)) dlogger.debug("Running as systemd watchdog service") dlogger.debug("WATCHDOG_USEC = %s", WATCHDOG_USEC) dlogger.debug("WATCHDOG_PID = %s", WATCHDOG_PID) loop.create_task(periodic_watchdog()) # Get socket for config name. sockpath = sockpath_for_config(config_name) dlogger.debug(f"Socket path: '{sockpath}'") # Clean up old socket. try: os.remove(sockpath) except FileNotFoundError: pass # Expose maestral as Pyro server. Convert management # methods to one way calls so that they don't block. dlogger.debug("Creating Pyro daemon") ExposedMaestral = expose(Maestral) ExposedMaestral.start_sync = oneway(ExposedMaestral.start_sync) ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.shutdown_daemon = oneway(ExposedMaestral.shutdown_daemon) maestral_daemon = ExposedMaestral(config_name, log_to_stderr=log_to_stderr) if start_sync: dlogger.debug("Starting sync") maestral_daemon.start_sync() try: dlogger.debug("Starting event loop") with Daemon(unixsocket=sockpath) as daemon: daemon.register(maestral_daemon, f"maestral.{config_name}") # Reduce Pyro's housekeeping frequency from 2 sec to 20 sec. # This avoids constantly waking the CPU when we are idle. if daemon.transportServer.housekeeper: daemon.transportServer.housekeeper.waittime = 20 for socket in daemon.sockets: loop.add_reader(socket.fileno(), daemon.events, daemon.sockets) # Handle sigterm gracefully. signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT) for s in signals: loop.add_signal_handler(s, maestral_daemon.shutdown_daemon) loop.run_until_complete(maestral_daemon.shutdown_complete) for socket in daemon.sockets: loop.remove_reader(socket.fileno()) # Prevent Pyro housekeeping from blocking shutdown. daemon.transportServer.housekeeper = None except Exception as exc: dlogger.error(exc.args[0], exc_info=True) finally: if NOTIFY_SOCKET: # Notify systemd that we are shutting down. sd_notifier.notify("STOPPING=1")
def start_maestral_daemon(config_name: str = "maestral", log_to_stdout: bool = False, start_sync: bool = False) -> None: """ Starts the Maestral daemon with event loop in the current thread. Startup is race free: there will never be two daemons running for the same config. Wraps :class:`main.Maestral` as Pyro daemon object, creates a new instance and starts an asyncio event loop to listen for requests on a unix domain socket. This call will block until the event loop shuts down. When this function is called from the main thread on macOS, the asyncio event loop uses Cocoa's CFRunLoop to process event. This allows integration with Cocoa frameworks which use callbacks to process use input such as clicked notifications, etc, and potentially allows showing a GUI. :param config_name: The name of the Maestral configuration to use. :param log_to_stdout: If ``True``, write logs to stdout. :param start_sync: If ``True``, start syncing once the daemon has started. :raises: :class:`RuntimeError` if a daemon for the given ``config_name`` is already running. """ import asyncio from maestral.main import Maestral if threading.current_thread() is not threading.main_thread(): raise RuntimeError("Must run daemon in main thread") # acquire PID lock file lock = maestral_lock(config_name) if not lock.acquire(): raise RuntimeError("Maestral daemon is already running") # Nice ourselves to give other processes priority. We will likely only # have significant CPU usage in case of many concurrent downloads. os.nice(10) # catch sigterm and shut down gracefully signal.signal(signal.SIGTERM, _sigterm_handler) # integrate with CFRunLoop in macOS, only works in main thread if sys.platform == "darwin": logger.debug("Cancelling all tasks from asyncio event loop") from rubicon.objc.eventloop import EventLoopPolicy # type: ignore # clean up any pending tasks before we change the event loop policy # this is necessary if previous code has run an asyncio loop loop = asyncio.get_event_loop() try: # Python 3.7 and higher all_tasks = asyncio.all_tasks(loop) except AttributeError: # Python 3.6 all_tasks = asyncio.Task.all_tasks(loop) pending_tasks = [t for t in all_tasks if not t.done()] for task in pending_tasks: task.cancel() loop.run_until_complete( asyncio.gather(*pending_tasks, return_exceptions=True)) loop.close() logger.debug("Integrating with CFEventLoop") # set new event loop policy asyncio.set_event_loop_policy(EventLoopPolicy()) # get the default event loop loop = asyncio.get_event_loop() sd_notifier = sdnotify.SystemdNotifier() # notify systemd that we have started if NOTIFY_SOCKET: logger.debug("Running as systemd notify service") logger.debug("NOTIFY_SOCKET = %s", NOTIFY_SOCKET) sd_notifier.notify("READY=1") # notify systemd periodically if alive if IS_WATCHDOG and WATCHDOG_USEC: async def periodic_watchdog() -> None: if WATCHDOG_USEC: sleep = int(WATCHDOG_USEC) while True: sd_notifier.notify("WATCHDOG=1") await asyncio.sleep(sleep / (2 * 10**6)) logger.debug("Running as systemd watchdog service") logger.debug("WATCHDOG_USEC = %s", WATCHDOG_USEC) logger.debug("WATCHDOG_PID = %s", WATCHDOG_PID) loop.create_task(periodic_watchdog()) # get socket for config name sockpath = sockpath_for_config(config_name) logger.debug(f"Socket path for '{config_name}' daemon: '{sockpath}'") # clean up old socket try: os.remove(sockpath) except FileNotFoundError: pass # expose maestral as Pyro server # convert management methods to one way calls so that they don't block logger.debug("Creating Pyro daemon") ExposedMaestral = expose(Maestral) ExposedMaestral.start_sync = oneway(ExposedMaestral.start_sync) ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.pause_sync = oneway(ExposedMaestral.pause_sync) ExposedMaestral.resume_sync = oneway(ExposedMaestral.resume_sync) ExposedMaestral.shutdown_daemon = oneway(ExposedMaestral.shutdown_daemon) maestral_daemon = ExposedMaestral(config_name, log_to_stdout=log_to_stdout) if start_sync: logger.debug("Starting sync") maestral_daemon.start_sync() try: logger.debug("Starting event loop") with Daemon(unixsocket=sockpath) as daemon: daemon.register(maestral_daemon, f"maestral.{config_name}") for socket in daemon.sockets: loop.add_reader(socket.fileno(), daemon.events, daemon.sockets) loop.run_until_complete(maestral_daemon.shutdown_complete) for socket in daemon.sockets: loop.remove_reader(socket.fileno()) except Exception: traceback.print_exc() finally: if NOTIFY_SOCKET: # notify systemd that we are shutting down sd_notifier.notify("STOPPING=1")