=== modified file 'powernap/monitors/InputMonitor.py' --- powernap/monitors/InputMonitor.py 2011-08-19 16:43:59 +0000 +++ powernap/monitors/InputMonitor.py 2014-02-13 18:05:46 +0000 @@ -20,6 +20,7 @@ import os, re, threading import select +import time from fcntl import fcntl, F_NOTIFY, DN_CREATE, DN_DELETE, DN_MULTISHOT from logging import error, debug, info, warn @@ -47,34 +48,44 @@ self._regex = re.compile(config['regex']) # Register for directory events / setup input watches - self._inputs = {} - self._poll = select.poll() + self._clear_inputs() self._update_inputs() self._dd = os.open(self._path, 0) fcntl(self._dd, F_NOTIFY, DN_DELETE | DN_CREATE | DN_MULTISHOT) + + # clear / unregister / close input events + def _clear_inputs ( self ): + info("%s unregister inputs"%(self._name)) + self._poll = select.poll() + self._registered = False + self._inputs = {} + # Update the input events list def _update_inputs ( self ): + info("%s update inputs"%(self._name)) + events = {} event = None # Name of the event to poll, after finding it evpath = None # Absolute path of the event to poll # Search for the event in path: + # There can be several such events. for str in os.listdir(self._path): match = self._regex.search(str) if match: event = str evpath = os.path.abspath(os.path.join(self._path, event)) - break - - # If event is different from None, then update! - if event: - if os.path.exists(evpath): - fp = open(evpath) - events[evpath] = fp - # Register the event to poll - self._poll.register(fp.fileno(), select.POLLIN|select.POLLPRI) - self._inputs = events + info("For path: %s found event: %s"%(self._path, event)) + if os.path.exists(evpath): + fp = open(evpath) + if fp: + events[evpath] = fp + # Register the event to poll + self._poll.register(fp.fileno(), select.POLLIN|select.POLLPRI) + self._inputs = events + self._registered = True + info("Registered event: %s"%(evpath)) # Start the thread def start ( self ): @@ -89,12 +100,23 @@ # Poll for events while self._running: - res = self._poll.poll(1000) - if ( res ): - for fd, e in res: - if e & (select.POLLIN|select.POLLPRI): - os.read(fd, 32768) # Read what is there! - self._input_received = True + if self._registered: + res = self._poll.poll(1000) + if ( res ): + for fd, e in res: + # poll() may have returned with error and no delay + # sleep for 1 s if there was an error to avoid 100 % CPU + # then try to re-open the file + if e & (select.POLLERR|select.POLLHUP|select.POLLNVAL): + info("%s poll error: %i"%(self._name, e)) + time.sleep(1) + self._clear_inputs() + elif e & (select.POLLIN|select.POLLPRI): + os.read(fd, 32768) # Read what is there! + self._input_received = True + else: + self._update_inputs() + time.sleep(1) def active(self): if self._input_received: