add path timeout for sensitive devices

This commit is contained in:
petrucci4prez 2017-05-30 01:00:23 -04:00
parent c002fc08eb
commit dd00c560eb
2 changed files with 38 additions and 33 deletions

View File

@ -49,46 +49,51 @@ class CountdownTimer(Thread):
def __del__(self): def __del__(self):
self.stop() self.stop()
def waitForPath(path, timeout=30):
for i in range(0, timeout):
if os.path.exists(path):
return
time.sleep(1)
raise FileNotFoundError('Could not find {} after {} seconds'.format(path, timeout))
def freeBusyPath(path, logger=None): # we shouldn't need this if we are disabling the usb hub globally and nuking any past connections
# check if any other processes are using file path #~ def freeBusyPath(path, logger=None):
# if found, politely ask them to exit, else nuke them #~ # check if any other processes are using file path
#~ # if found, politely ask them to exit, else nuke them
# NOTE: fuser sends diagnostic info (eg filenames and modes...which we #~ # NOTE: fuser sends diagnostic info (eg filenames and modes...which we
# don't want) to stderr. This is weird, but let's me route to /dev/null #~ # don't want) to stderr. This is weird, but let's me route to /dev/null
# so I don't have to parse it later #~ # so I don't have to parse it later
try: #~ try:
stdout = check_output(['fuser', path], universal_newlines=True, stderr=DEVNULL) #~ stdout = check_output(['fuser', path], universal_newlines=True, stderr=DEVNULL)
except CalledProcessError: #~ except CalledProcessError:
logger.debug('%s not in use. Execution may continue', path) #~ logger.debug('%s not in use. Execution may continue', path)
else: #~ else:
# assume stdout is one PID first #~ # assume stdout is one PID first
try: #~ try:
processes = [psutil.Process(int(stdout))] #~ processes = [psutil.Process(int(stdout))]
# else assume we have multiple PIDs separated by arbitrary space #~ # else assume we have multiple PIDs separated by arbitrary space
except ValueError: #~ except ValueError:
processes = [psutil.Process(int(s)) for s in stdout.split()] #~ processes = [psutil.Process(int(s)) for s in stdout.split()]
for p in processes: #~ for p in processes:
if logger: #~ if logger:
logger.warning('%s in use by PID %s. Sending SIGTERM', path, p.pid) #~ logger.warning('%s in use by PID %s. Sending SIGTERM', path, p.pid)
p.terminate() #~ p.terminate()
dead, alive = psutil.wait_procs(processes, timeout=10) #~ dead, alive = psutil.wait_procs(processes, timeout=10)
for p in alive: #~ for p in alive:
if logger: #~ if logger:
logger.warning('Failed to terminate PID %s. Sending SIGKILL', p.pid) #~ logger.warning('Failed to terminate PID %s. Sending SIGKILL', p.pid)
p.kill() #~ p.kill()
# crude way to 'unplug and plug back in' for USB device # crude way to reset USB device, pretty rough but works
def resetUSBDevice(device): def resetUSBDevice(device):
devpath = os.path.join('/sys/bus/usb/devices/' + device + '/authorized') devpath = os.path.join('/sys/bus/usb/devices/' + device + '/authorized')
with open(devpath, 'w') as f: with open(devpath, 'w') as f:
f.write('0') f.write('0')
with open(devpath, 'w') as f: with open(devpath, 'w') as f:
f.write('1') f.write('1')
def fallbackLogger(module, loglevel, msg):
print('[{}] [{}] [FALLBACK LOGGER]: {}'.format(module, loglevel, msg))

View File

@ -2,7 +2,7 @@ import logging, os, sys, stat
from threading import Thread from threading import Thread
from evdev import InputDevice, ecodes from evdev import InputDevice, ecodes
from select import select from select import select
from auxilary import freeBusyPath from auxilary import waitForPath, freeBusyPath
import stateMachine import stateMachine
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -22,9 +22,9 @@ class KeypadListener(Thread):
} }
devPath = '/dev/input/by-id/usb-04d9_1203-event-kbd' devPath = '/dev/input/by-id/usb-04d9_1203-event-kbd'
freeBusyPath(devPath, logger)
waitForPath(devPath)
self._dev = InputDevice(devPath) self._dev = InputDevice(devPath)
self._dev.grab() self._dev.grab()