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

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