Avoid race condition during config update

This commit is contained in:
Peter J. Holzer 2023-09-20 10:50:29 +02:00
parent aa66f8d615
commit 1a0ccb22b7
1 changed files with 15 additions and 3 deletions

18
app.py
View File

@ -97,8 +97,9 @@ def verify_node(d):
if "/" in node: if "/" in node:
raise ValueError("invalid node name %s", node) raise ValueError("invalid node name %s", node)
try: try:
log.info("getting client config from %s", "config/" + node) fn = "config/" + node
with open("config/" + node) as fh: log.info("getting client config from %s", fn)
with open(fn) as fh:
node_conf = json.load(fh) node_conf = json.load(fh)
except Exception as e: except Exception as e:
log.warning("got %s opening %s", e, "config/" + node) log.warning("got %s opening %s", e, "config/" + node)
@ -112,8 +113,19 @@ def verify_node(d):
if timestamp > node_conf["last"]: if timestamp > node_conf["last"]:
node_conf["last"] = timestamp node_conf["last"] = timestamp
os.replace("config/" + node, "config/" + node + ".old") os.replace("config/" + node, "config/" + node + ".old")
with open("config/" + node, "w") as fh: tmpfn = fn + "." + str(os.getpid())
oldfn = fn + ".old"
with open(tmpfn, "w") as fh:
json.dump(node_conf, fh) # XXX json.dump(node_conf, fh) # XXX
try:
os.unlink(oldfn)
except FileNotFoundError:
pass
try:
os.link(fn, oldfn)
except FileNotFoundError:
pass
os.rename(tmpfn, fn)
return node return node
else: else:
abort(409, "timestamp out of sync") abort(409, "timestamp out of sync")