Skip to content

Commit

Permalink
fix critical put and get param that caused sporadic controlsd hanging (
Browse files Browse the repository at this point in the history
…#333)

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

* test fix
  • Loading branch information
rbiasini committed Aug 25, 2018
1 parent c29b311 commit b942ab5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 21 deletions.
53 changes: 38 additions & 15 deletions common/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,23 +263,48 @@ def __exit__(self, type, value, traceback):
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)
Expand All @@ -291,16 +316,15 @@ def car_start(self):
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):
if key not in keys:
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?
Expand All @@ -311,8 +335,7 @@ def put(self, key, dat):
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()
Expand Down
6 changes: 0 additions & 6 deletions selfdrive/controls/controlsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

4 comments on commit b942ab5

@adhintz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After merging this in to my fork, the training UI was displayed, but after completing the training, baseui crashed.

@tentious
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. After reverting this commit in my fork, the baseui error goes away.

@rbiasini
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, fixed in next commit

@tentious
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirming that PR #337 fixes this in my fork.

Please sign in to comment.