Use os.rename() in async_wrapper

Because the async_status module will read from the same file that
the async_wrapper module is writing, it's possible that the file
may not be fully synced during a read, causing spurious failures.
Use a temp file to do an atomic operation on the file. We can't
use atomic_move() here as that doesn't work properly under async.

Also, let's not read concurrently from the same file the subprocess
is writing to. Instead, capture stdout/stderr via PIPE and write to
the file to avoid nasty races.
pull/18777/head
David Shrewsbury 9 years ago committed by Matt Clay
parent f9cb5ecc3c
commit 88122e0f72

@ -72,19 +72,23 @@ def daemonize_self():
def _run_module(wrapped_cmd, jid, job_path): def _run_module(wrapped_cmd, jid, job_path):
jobfile = open(job_path, "w") tmp_job_path = job_path + ".tmp"
jobfile = open(tmp_job_path, "w")
jobfile.write(json.dumps({ "started" : 1, "ansible_job_id" : jid })) jobfile.write(json.dumps({ "started" : 1, "ansible_job_id" : jid }))
jobfile.close() jobfile.close()
jobfile = open(job_path, "w") os.rename(tmp_job_path, job_path)
jobfile = open(tmp_job_path, "w")
result = {} result = {}
outdata = '' outdata = ''
try: try:
cmd = shlex.split(wrapped_cmd) cmd = shlex.split(wrapped_cmd)
script = subprocess.Popen(cmd, shell=False, stdin=None, stdout=jobfile, stderr=jobfile) script = subprocess.Popen(cmd, shell=False, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
script.communicate() (outdata, stderr) = script.communicate()
outdata = file(job_path).read()
result = json.loads(outdata) result = json.loads(outdata)
if stderr:
result['stderr'] = stderr
jobfile.write(json.dumps(result))
except (OSError, IOError): except (OSError, IOError):
e = sys.exc_info()[1] e = sys.exc_info()[1]
@ -95,6 +99,7 @@ def _run_module(wrapped_cmd, jid, job_path):
} }
result['ansible_job_id'] = jid result['ansible_job_id'] = jid
jobfile.write(json.dumps(result)) jobfile.write(json.dumps(result))
except: except:
result = { result = {
"failed" : 1, "failed" : 1,
@ -104,7 +109,9 @@ def _run_module(wrapped_cmd, jid, job_path):
} }
result['ansible_job_id'] = jid result['ansible_job_id'] = jid
jobfile.write(json.dumps(result)) jobfile.write(json.dumps(result))
jobfile.close() jobfile.close()
os.rename(tmp_job_path, job_path)
#################### ####################

Loading…
Cancel
Save