예제 #1
0
  def stop(self, *args, **kwargs):
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)

    GPIO.setup(self.rpin,GPIO.OUT)
    GPIO.setup(self.gpin,GPIO.OUT)
    GPIO.setup(self.bpin,GPIO.OUT)
    self.rled = GPIO.PWM(self.rpin,self.freq)
    self.gled = GPIO.PWM(self.gpin,self.freq)
    self.bled = GPIO.PWM(self.bpin,self.freq)

    self.rled.ChangeDutyCycle(0)
    self.gled.ChangeDutyCycle(0)
    self.bled.ChangeDutyCycle(50)
    time.sleep(1)
    self.rled.stop()
    self.gled.stop()
    self.bled.stop()
    GPIO.cleanup()

    if os.path.exists(self.cf):
      os.remove(self.cf)

    if os.path.exists(self.bf):
      os.remove(self.bf)

    Daemon.stop(self, *args, **kwargs)
예제 #2
0
파일: client.py 프로젝트: hsbp/burnstation2
class TorrentClient(object):
    def __init__(self, hostname=None, port=9090):
        self.daemon = None
        if not hostname:
            self.daemon = Daemon(["transmission-daemon", "-f", "-p", str(port)])
            self.daemon.start()
            hostname = "localhost"
        self._connection = TransmissionConnection(hostname, port)
        self._session = self._connection.execute(Command("session-get"))
        
    def __del__(self):
        if self.daemon:
            self.daemon.stop()
            
    def add_torrent(self, auto=None, metadata=None, filename=None, file=None, url=None):
        if auto:
            if isinstance(auto, str):
                if "://" in auto:
                    data = urllib2.urlopen(auto).read()
                else:
                    data = open(auto, "r").read()
            elif hasattr(auto, "read"):
                data = auto.read()
            elif hasattr(auto, "content"):
                data = auto.content
            else:
                raise AttributeError()
        else:
            if metadata:
                data = metadata
            elif filename:
                data = open(filename, "r").read()
            elif url:
                data = urllib2.urlopen(url).read()
            elif file:
                data = file.read()

        data = base64.encodestring(data)
        
        command = Command("torrent-add")
        command["metainfo"] = data
        command["paused"] = True
            
        torrent = self._connection.execute(command)
        return self.get_torrent(torrent["torrent-added"]["id"])
            
    def get_torrent(self, id):
        command = TorrentGetCommand(Torrent.static_fields, id)
        torrent = self._connection.execute(command)
        return Torrent(self, torrent)

    def _get_torrents(self):
        command = TorrentGetListCommand(Torrent.static_fields)
        list = self._connection.execute(command)
        torrent_list = map(lambda t: Torrent(self, t), list)
        return torrent_list
    
    download_dir = session_property("download-dir")
    torrents = property(_get_torrents)
예제 #3
0
 def stop(self):
     configuration = self._core.get_configuration()
     if os.path.exists(
             configuration.get_entry("core.webpath") +
             "/scv_operating.lck"):
         os.remove(
             configuration.get_entry("core.webpath") + "/scv_operating.lck")
     Daemon.stop(self)
예제 #4
0
 def stop(self):
   """Override for inherited stop method of Daemon class.
   Right now this just logs that the classifier is stopping.
   
   """
   self.log.print_log("classifier daemon is shutting down (pid %s)" % str(os.getpid()))
   if self.status_filename and os.path.exists(self.status_filename):
     os.remove(self.status_filename)
   Daemon.stop(self)
예제 #5
0
 def stop(self):
     try:
         print 'Flushing data cache....'
         external_flush()
         #The data cache needs time to flush the messages before stopping the process
         time.sleep(5)
         Daemon.stop(self) 
     except Exception as e:
         print e
예제 #6
0
파일: statusdaemon.py 프로젝트: sohonet/HEN
 def stopDaemon(self,prot,seq,ln,payload):
     """\brief Stops the daemon and all threads
     This method will first stop any more incoming queries, then wait for
     any update tasks to complete, before stopping itself.
     """
     log.debug("stopDaemon called.")
     prot.sendReply(200, seq, "Accepted stop request.")
     log.debug("Stopping Checker Timer")
     self.__checker_timer.stop()
     self.acceptConnections(False)
     log.debug("Stopping Hen Status Daemon (self)")
     Daemon.stop(self)
예제 #7
0
def main():
    doers = _get_doers(shell)
    doers.update(_get_doers(utils))

    possible_actions = doers.keys() + ['start', 'stop', 'status']

    args = arguments.get_args(possible_actions)

    if args.action is None:
        print "No action"
        sys.exit(1)

    apiclient = None
    if args.no_api is False:
        os_options = arguments.OpenstackOptions(args, os.environ)
        if args.debug:
            print os_options
        apiclient = client.Client(username=os_options.username,
                                  password=os_options.password,
                                  tenant_name=os_options.tenant_name,
                                  endpoint=os_options.endpoint,
                                  auth_url=os_options.auth_url)
        if args.client_id:
            apiclient.client_id = args.client_id

    if args.action in doers:
        try:
            return doers[args.action](apiclient, args)
        except Exception as e:
            print ('ERROR {0}'.format(e))
            return 1

    create_dir(args.jobs_dir, do_log=False)

    freezer_scheduler = FreezerScheduler(apiclient=apiclient,
                                         interval=int(args.interval),
                                         job_path=args.jobs_dir)

    daemon = Daemon(daemonizable=freezer_scheduler)

    if args.action == 'start':
        daemon.start(log_file=args.log_file)
    elif args.action == 'stop':
        daemon.stop()
    elif args.action == 'reload':
        daemon.reload()
    elif args.action == 'status':
        daemon.status()

    return os.EX_OK
예제 #8
0
def daemon_main():
    configure_logging()
    daemon = None
    logger = logging.getLogger("daemon.main")
    try:
        daemon = Daemon('http://illuminant:11311')
        daemon.start()
        while daemon.ok():
            time.sleep(.1)
    except KeyboardInterrupt:
        if daemon is not None:
            daemon.stop()
    except Exception as e:
        logger.error("error occurred, {}".format(e))
예제 #9
0
파일: recbate.py 프로젝트: stbkde/recbate
def bot():
    if not check_num_args(2): return
    
    # make daemon inst
    daemon = Daemon()

    # start, stop or restart
    if sys.argv[1] == "start":
        daemon.start()
    
    elif sys.argv[1] == "stop":
        daemon.stop()
    
    elif sys.argv[1] == "restart":
        daemon.restart()
예제 #10
0
def bot():
    if not check_num_args(2): return

    # load config
    config = Config.load_config()

    # make daemon inst
    daemon = Daemon(config["pid_path"], config["log_path"])

    # start, stop or restart
    if sys.argv[1] == "start":
        daemon.start()

    elif sys.argv[1] == "stop":
        daemon.stop()

    elif sys.argv[1] == "restart":
        daemon.restart()
예제 #11
0
def main():
	pidfile = None
	d = None
	for i in range(1, len(sys.argv)):
		arg = sys.argv[i]
		if arg.startswith('--auth='):
			auth_error = auth_file_load(arg[len('--auth='):])
			if not auth_error is None:
				print('Bad auth file: ' + auth_error)
				sys.exit(1)
	if len(sys.argv) > 2:
		if sys.argv[1] == 'daemonize':
			pidfile = sys.argv[2]
			# Reloader will spawn new process with args
			del(sys.argv[2])
			del(sys.argv[1])
			d = Daemon(pidfile)
			d.start(run)
		elif sys.argv[1] == 'stop':
			pidfile = sys.argv[2]
			d = Daemon(pidfile)
			d.stop(24)
	if d is None:
		run()
예제 #12
0
 def stop(self):
     configuration = self._core.get_configuration()
     if os.path.exists(configuration.get_entry("core.webpath")+"/scv_operating.lck"):
         os.remove(configuration.get_entry("core.webpath")+"/scv_operating.lck") 
     Daemon.stop(self)
예제 #13
0
def main():  # pragma: no cover
    """
    main method
    """
    usage = [
        sys.argv[0] + " [option] (--start|--stop) <form_definition.json>",
        "       " + sys.argv[0] + " --generate-pw",
    ]
    parser = optparse.OptionParser(version="%%VERSION%%")
    parser.set_usage('\n'.join(usage))

    parser.add_option("-g",
                      "--generate-pw",
                      dest="generate_pw",
                      action="store_true",
                      default=False,
                      help="Generate password")
    parser.add_option("-p",
                      "--port",
                      dest="port",
                      action="store",
                      type="int",
                      default=8081,
                      help="Port to listen on (default=8081)")
    parser.add_option("-f",
                      "--foreground",
                      dest="foreground",
                      action="store_true",
                      default=False,
                      help="Run in foreground (debugging)")
    parser.add_option("-r",
                      "--reload",
                      dest="reload",
                      action="store_true",
                      default=False,
                      help="Reload form config on every request (DEV)")
    parser.add_option("--pid-file",
                      dest="pid_file",
                      action="store",
                      default=None,
                      help="Pid file")
    parser.add_option("--log-file",
                      dest="log_file",
                      action="store",
                      default=None,
                      help="Log file")
    parser.add_option("--start",
                      dest="action_start",
                      action="store_true",
                      default=None,
                      help="Start daemon")
    parser.add_option("--stop",
                      dest="action_stop",
                      action="store_true",
                      default=None,
                      help="Stop daemon")

    (options, args) = parser.parse_args()

    if options.generate_pw:
        # Generate a password for use in the `users` section
        import getpass
        plain_pw = getpass.getpass()
        if plain_pw != getpass.getpass('Repeat password: '******'\n')
        sys.exit(0)
    else:
        if not options.action_stop and len(args) < 1:
            parser.error("Insufficient number of arguments")
        if not options.action_stop and not options.action_start:
            options.action_start = True

        # If a form configuration was specified, change to that dir so we can
        # find the job scripts and such.
        if args:
            path = os.path.dirname(args[0])
            if path:
                os.chdir(path)
            args[0] = os.path.basename(args[0])

        daemon = Daemon(options.pid_file,
                        options.log_file,
                        foreground=options.foreground)
        log = logging.getLogger('MAIN')
        try:
            if options.action_start:
                cache = not options.reload
                scriptform_instance = ScriptForm(args[0], cache=cache)
                daemon.register_shutdown_callback(scriptform_instance.shutdown)
                daemon.start()
                scriptform_instance.run(listen_port=options.port)
            elif options.action_stop:
                daemon.stop()
                sys.exit(0)
        except socket.error as err:
            log.exception(err)
            sys.stderr.write("Cannot bind to port {0}: {1}\n".format(
                options.port, str(err)))
            sys.exit(2)
        except Exception as err:
            log.exception(err)
            raise
예제 #14
0
파일: pimmer.py 프로젝트: adark47/pimmer
class Pimmer(object):

    do_restart = False

    def __init__(self):

        #parse args
        parser = ArgumentParser(prog='pimmer.py')
        parser.add_argument('--daemon',
                            action='store_true',
                            dest='daemon',
                            help='Daemonize the app')
        parser.add_argument('--pid_file',
                            dest='pid_file',
                            help='Path to pidfile needed for daemon')
        parser.add_argument(
            '-v',
            '--verbose',
            action='count',
            default=0,
            help='Increases verbosity of logging. See LOGFILE variable.')
        parser.add_argument('--console',
                            action='store_true',
                            dest='console',
                            help='Log to console')

        self.options = parser.parse_args()
        #configure logger
        self.configureLogging()

        self.log = PLog(__name__)

    def configureLogging(self):
        logfile = config.get("general", "log_file")
        logging.getLogger().setLevel(self.options.verbose)

        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s',
                                      '%H:%M:%S')
        hdlr = handlers.RotatingFileHandler(logfile, 'a', 500000, 10)
        hdlr.setLevel(self.options.verbose)
        hdlr.setFormatter(formatter)
        console = self.options.console == True
        console = True
        if console and not self.runAsDaemon():
            console = logging.StreamHandler()
            console.setLevel(self.options.verbose)
            console.setFormatter(formatter)
            logging.getLogger().addHandler(console)
        logging.getLogger().addHandler(hdlr)

    def daemonize(self):
        try:
            from daemon import Daemon
            self.daemon = Daemon(self.options.pid_file)

            self.daemon.daemonize()
            print "daemon"
        except SystemExit:
            raise
        except:
            self.log.critical(traceback.format_exc())

    def runAsDaemon(self):
        return self.options.daemon and self.options.pid_file

    def exit(self, signal, frame):
        self.log.info("Shutting down Pimmer")
        core.shutdown()
        sys.exit(0)

    def restart(self):
        try:
            if self.runAsDaemon():
                try:
                    self.daemon.stop()
                except:
                    pass
        except:
            self.log.critical(traceback.format_exc())

        os.chdir(base_path)

        args = [sys.executable] + [
            os.path.join(base_path, os.path.basename(__file__))
        ] + sys.argv[1:]
        self.log.info('Re-spawning %s' % ' '.join(args))
        subprocess.Popen(args)

    def run(self):

        signal.signal(signal.SIGINT, self.exit)
        signal.signal(signal.SIGTERM, lambda signum, stack_frame: sys.exit(1))

        try:
            core.initialize()
            core.run()
        except KeyboardInterrupt:
            pass
        except Exception:
            self.log.error(traceback.format_exc())

            if self.do_restart:
                self.log.info("Going to sleep 2 seconds and restart")
                time.sleep(2)
                self.restart()
        '-e',
        '--ext',
        action='append',
        help='allowed file extensions (without .) May occur more than once')

    args = parser.parse_args()

    dm = Daemon(user=args.user,
                rootdir=args.root_dir,
                pidfile=args.pid_file,
                force=args.force,
                logfile=args.log_file,
                name=args.name)

    if args.stop:
        dm.stop()
    else:
        server_address = (args.bind, args.port)
        RestrictedHTTPRequestHandler.protocol_version = "HTTP/1.0"
        RestrictedHTTPRequestHandler.logfie = lambda self, msg: dm.log(
            logging.INFO, msg)
        RestrictedHTTPRequestHandler.extensions = args.ext if args.ext is not None else None
        RestrictedHTTPRequestHandler.nodirlist = args.nodirlist

        with HTTPServer(server_address, RestrictedHTTPRequestHandler) as httpd:
            sa = httpd.socket.getsockname()
            serve_message = "Serving HTTP on {host} port {port} (http://{host}:{port}/) ..."
            dm.log(logging.INFO, serve_message.format(host=sa[0], port=sa[1]))
            dm.keep(httpd.socket.fileno())
            if args.debug:
                print("running in foreground")
예제 #16
0
 def stop(self):
     self.db.close()
     Daemon.stop(self)
예제 #17
0
 def stop(self):
     # TODO: Stop the fswatcher and the web server
     self.exit()
     Daemon.stop(self)
예제 #18
0
def main():  # pragma: no cover
    """
    main method
    """
    usage = [
        sys.argv[0] + " [option] (--start|--stop) <form_definition.json>",
        "       " + sys.argv[0] + " --generate-pw",
    ]
    parser = optparse.OptionParser(version="%%VERSION%%")
    parser.set_usage('\n'.join(usage))

    parser.add_option("-g", "--generate-pw", dest="generate_pw",
                      action="store_true", default=False,
                      help="Generate password")
    parser.add_option("-p", "--port", dest="port", action="store", type="int",
                      default=80, help="Port to listen on (default=80)")
    parser.add_option("-f", "--foreground", dest="foreground",
                      action="store_true", default=False,
                      help="Run in foreground (debugging)")
    parser.add_option("-r", "--reload", dest="reload", action="store_true",
                      default=False,
                      help="Reload form config on every request (DEV)")
    parser.add_option("--pid-file", dest="pid_file", action="store",
                      default=None, help="Pid file")
    parser.add_option("--log-file", dest="log_file", action="store",
                      default=None, help="Log file")
    parser.add_option("--start", dest="action_start", action="store_true",
                      default=None, help="Start daemon")
    parser.add_option("--stop", dest="action_stop", action="store_true",
                      default=None, help="Stop daemon")

    (options, args) = parser.parse_args()

    if options.generate_pw:
        # Generate a password for use in the `users` section
        import getpass
        plain_pw = getpass.getpass()
        if not plain_pw == getpass.getpass('Repeat password: '******'\n')
        sys.exit(0)
    else:
        if not options.action_stop and len(args) < 1:
            parser.error("Insufficient number of arguments")
        if not options.action_stop and not options.action_start:
            options.action_start = True

        # If a form configuration was specified, change to that dir so we can
        # find the job scripts and such.
        if len(args) > 0:
            path = os.path.dirname(args[0])
            if path:
                os.chdir(path)
            args[0] = os.path.basename(args[0])

        daemon = Daemon(options.pid_file, options.log_file,
                        foreground=options.foreground)
        log = logging.getLogger('MAIN')
        try:
            if options.action_start:
                cache = not options.reload
                scriptform_instance = ScriptForm(args[0], cache=cache)
                daemon.register_shutdown_callback(scriptform_instance.shutdown)
                daemon.start()
                scriptform_instance.run(listen_port=options.port)
            elif options.action_stop:
                daemon.stop()
                sys.exit(0)
        except socket.error as err:
            log.exception(err)
            sys.stderr.write("Cannot bind to port {0}: {1}\n".format(
                options.port,
                str(err)
            ))
            sys.exit(2)
        except Exception as err:
            log.exception(err)
            raise
예제 #19
0
 def stop(self):
     # TODO: Stop the fswatcher and the web server
     self.exit()
     Daemon.stop(self)
예제 #20
0
 def stop(self):
     try:
         self.ioloop.stop()
     finally:
         Daemon.stop(self)
예제 #21
0
                self.stopold()
                self._couples = newcouples
                i = 1
            else:
                i = i + 1
            time.sleep(self._option['sleep'])
        self.stopold()


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print "Usage : python couplemanager.py [start|stop|restart|run]"
        sys.exit(2)

    mode = sys.argv[1]
    runner = CoupleManager('../conf/cpmng.conf')
    adaemon = Daemon('cpmng', runner)
    if 'start' == mode:
        adaemon.start()
    elif 'stop' == mode:
        adaemon.stop()
    elif 'restart' == mode:
        adaemon.restart()
    elif 'run' == mode:
        adaemon.run()
    else:
        print "Unknown command"
        sys.exit(2)
    sys.exit(0)
예제 #22
0
    try:
        eventlet.serve(eventlet.listen((HOST, PORT)), handle,
                       concurrency=CONCURRENCY)
    except socket.error as e:
        log.warn(e)
        eventlet.StopServe()
        sys.exit(0)


if __name__ == "__main__":
    d = Daemon("/tmp/simplemta.pid")
    if sys.argv[1] == "start":
        log.info("Starting SimpleMTA %s:%s..." % (HOST, PORT))
        d.start()
    elif sys.argv[1] == "restart":
        log.info("Restarting SimpleMTA %s:%s..." % (HOST, PORT))
        eventlet.StopServe()
        d.restart()
    else:
        log.info("Stopping SimpleMTA...")
        eventlet.StopServe()
        d.stop()
        sys.exit(0)
    try:
        main()
    except (SystemExit, KeyboardInterrupt):
        log.info("Stopping SimpleMTA...")
        eventlet.StopServe()
        d.stop()
        sys.exit(0)
예제 #23
0
파일: pimmer.py 프로젝트: arsac/pimmer
class Pimmer(object):

  do_restart = False
    
  def __init__(self):
    
    #parse args
    parser = ArgumentParser(prog = 'pimmer.py')
    parser.add_argument('--daemon', action = 'store_true', dest = 'daemon', help = 'Daemonize the app')
    parser.add_argument('--pid_file', dest = 'pid_file', help = 'Path to pidfile needed for daemon')
    parser.add_argument('-v', '--verbose', action='count', default=0, help='Increases verbosity of logging. See LOGFILE variable.')
    parser.add_argument('--console', action = 'store_true', dest = 'console', help = 'Log to console')
    
    self.options = parser.parse_args()
    #configure logger
    self.configureLogging()
    
    self.log = PLog(__name__)
  
  def configureLogging(self):
    logfile = config.get("general","log_file")
    logging.getLogger().setLevel(self.options.verbose)
  
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s', '%H:%M:%S')
    hdlr = handlers.RotatingFileHandler(logfile, 'a', 500000, 10)
    hdlr.setLevel(self.options.verbose)
    hdlr.setFormatter(formatter)
    console = self.options.console == True
    console = True
    if console and not self.runAsDaemon():
        console = logging.StreamHandler()
        console.setLevel(self.options.verbose)
        console.setFormatter(formatter)
        logging.getLogger().addHandler(console)
    logging.getLogger().addHandler(hdlr)
  
  def daemonize(self):
    try:
      from daemon import Daemon
      self.daemon = Daemon(self.options.pid_file)
      
      self.daemon.daemonize()
      print "daemon"
    except SystemExit:
      raise
    except:
      self.log.critical(traceback.format_exc())
    
  def runAsDaemon(self):
    return self.options.daemon and self.options.pid_file
        
  def exit(self, signal, frame):
    self.log.info("Shutting down Pimmer")
    core.shutdown()
    sys.exit(0)
  
  def restart(self):
    try:
      if self.runAsDaemon():
        try: self.daemon.stop()
        except: pass
    except:
      self.log.critical(traceback.format_exc())
                
    os.chdir(base_path)
    
    args = [sys.executable] + [os.path.join(base_path, os.path.basename(__file__))] + sys.argv[1:]
    self.log.info('Re-spawning %s' % ' '.join(args))
    subprocess.Popen(args)
    
  def run(self):
    
    signal.signal(signal.SIGINT, self.exit)
    signal.signal(signal.SIGTERM, lambda signum, stack_frame: sys.exit(1))
    
    try:
      core.initialize()
      core.run()
    except KeyboardInterrupt:
        pass
    except Exception:
      self.log.error(traceback.format_exc())
      
      if self.do_restart:
        self.log.info("Going to sleep 2 seconds and restart")
        time.sleep(2)
        self.restart()
예제 #24
0
 def stop(self):
     self.stop_all()
     Daemon.stop(self)
예제 #25
0
 def stop(self, *args, **kwargs):
     logging.info("XiaomiBTDaemon stopped!!!")
     Daemon.stop(self, *args, **kwargs)
예제 #26
0
            print '-' * 80
            print message
            print
            sock.sendall(message)
            time.sleep(delay)


class Daemon(Daemon):
    def run(self):
        # Or simply merge your code with MyDaemon.
        client = Client()
        client.run()


if __name__ == "__main__":
    daemon = Daemon('/tmp/poller-daemon.pid')
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()
        elif 'stop' == sys.argv[1]:
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            daemon.restart()
        else:
            print "Unknown command"
            sys.exit(2)
        sys.exit(0)
    else:
        print "usage: %s start|stop|restart" % sys.argv[0]
        sys.exit(2)
예제 #27
0
파일: ubrs.py 프로젝트: lyon-esport/ubrs
 def stop(self):
     tornado.ioloop.IOLoop.instance().stop()
     self.relay.stop_and_clean()
     Daemon.stop(self)
예제 #28
0
파일: pyrasol.py 프로젝트: jsanborn/pyrasol
 def stop(self):
     Daemon.stop(self)
예제 #29
0
 def stop(self):
     if not reactor._stopped:
         reactor.stop()
         
     Daemon.stop(self)
예제 #30
0
파일: daemoncon.py 프로젝트: arifwn/AQMRPC
 # Do not use relative path!
 stdoutfile = os.getcwd() + '/stdout.txt'
 stderrfile = os.getcwd() + '/stderr.txt'
 address = 'localhost'
 port = settings.port
 
 daemon = Daemon(stdout=stdoutfile, stderr=stderrfile, address=address, port=port)
 
 if len(sys.argv) == 2:
     if 'start' == sys.argv[1]:
         daemon.start()
     elif 'stop' == sys.argv[1]:
         s = xmlrpclib.ServerProxy('http://localhost:%d'%port)
         try:
             pid = pidencrypt.solve_encripted_pid(s.status())
             daemon.stop(pid)
         except Exception, err:
             pass
     elif 'restart' == sys.argv[1]:
         s = xmlrpclib.ServerProxy('http://localhost:%d'%port)
         try:
             pid = pidencrypt.solve_encripted_pid(s.status())
             daemon.restart(pid)
         except Exception, err:
             print 'Stopped'
     elif 'status' == sys.argv[1]:
         s = xmlrpclib.ServerProxy('http://localhost:%d'%port)
         accessible = True
         try:
             s.status()
         except Exception, err:
예제 #31
0
 def stop(self):
     """Teardown."""
     for device in self.devices:
         device.ungrab()
     Daemon.stop(self)