fix critical put and get param that caused sporadic controlsd hanging (#333)

* fix critical put and get param that caused sporadic controlsd hanging

* test fix
pull/337/head
rbiasini 7 years ago committed by GitHub
parent c29b311583
commit b942ab58e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 53
      common/params.py
  2. 6
      selfdrive/controls/controlsd.py

@ -263,23 +263,48 @@ class DBWriter(DBAccessor):
self._lock = None
def read_db(params_path, key):
path = "%s/d/%s" % (params_path, key)
try:
with open(path, "rb") as f:
return f.read()
except IOError:
return None
class JSDB(object):
def __init__(self, fn):
self._fn = fn
def write_db(params_path, key, value):
lock = FileLock(params_path+"/.lock", True)
lock.acquire()
def begin(self, write=False):
if write:
return DBWriter(self._fn)
else:
return DBReader(self._fn)
try:
tmp_path = tempfile.mktemp(prefix=".tmp", dir=params_path)
with open(tmp_path, "wb") as f:
f.write(value)
f.flush()
os.fsync(f.fileno())
path = "%s/d/%s" % (params_path, key)
os.rename(tmp_path, path)
fsync_dir(os.path.dirname(path))
finally:
lock.release()
class Params(object):
def __init__(self, db='/data/params'):
self.env = JSDB(db)
self.db = db
# create the database if it doesn't exist...
if not os.path.exists(self.db+"/d"):
with self.transaction(write=True):
pass
def transaction(self, write=False):
if write:
return DBWriter(self.db)
else:
return DBReader(self.db)
def _clear_keys_with_type(self, tx_type):
with self.env.begin(write=True) as txn:
with self.transaction(write=True) as txn:
for key in keys:
if keys[key] == tx_type:
txn.delete(key)
@ -291,7 +316,7 @@ class Params(object):
self._clear_keys_with_type(TxType.CLEAR_ON_CAR_START)
def delete(self, key):
with self.env.begin(write=True) as txn:
with self.transaction(write=True) as txn:
txn.delete(key)
def get(self, key, block=False):
@ -299,8 +324,7 @@ class Params(object):
raise UnknownKeyName(key)
while 1:
with self.env.begin() as txn:
ret = txn.get(key)
ret = read_db(self.db, key)
if not block or ret is not None:
break
# is polling really the best we can do?
@ -311,8 +335,7 @@ class Params(object):
if key not in keys:
raise UnknownKeyName(key)
with self.env.begin(write=True) as txn:
txn.put(key, dat)
write_db(self.db, key, dat)
if __name__ == "__main__":
params = Params()

@ -448,12 +448,6 @@ def controlsd_thread(gctx=None, rate=100, default_bias=0.):
fcw_enabled = params.get("IsFcwEnabled") == "1"
geofence = None
try:
from selfdrive.controls.lib.geofence import Geofence
geofence = Geofence(params.get("IsGeofenceEnabled") == "1")
except ImportError:
# geofence not available
params.put("IsGeofenceEnabled", "-1")
PL = Planner(CP, fcw_enabled)
LoC = LongControl(CP, CI.compute_gb)

Loading…
Cancel
Save