Commit 0c412a5d authored by Kirill Smelkov's avatar Kirill Smelkov

XY wcfs: multiprocessing: Teach join to return what invoked function returned

For upcoming `wcfs status` we will need to be able to invoke functions
from stdlib and similar and retrieve their returned values.

XXX not sure the API is right. Maybe join should just join and return
value retrieved via .retvalue() method.
parent f4cf5aff
...@@ -79,14 +79,17 @@ class SubProcess(object): ...@@ -79,14 +79,17 @@ class SubProcess(object):
mod = importlib.import_module(modname) mod = importlib.import_module(modname)
f = getattr(mod, funcname) f = getattr(mod, funcname)
procname = kw.pop('_procname', funcpath) procname = kw.pop('_procname', funcpath)
_ = _END()
try: try:
f(*argv, **kw) r = f(*argv, **kw)
_ = 'END' _.ret = r
_.exc = None
except BaseException as exc: except BaseException as exc:
# dump traceback so it appears in the log because Traceback objects are not picklable # dump traceback so it appears in the log because Traceback objects are not picklable
print("\nException in subprocess %s (pid%d):" % (procname, os.getpid()), file=sys.stderr) print("\nException in subprocess %s (pid%d):" % (procname, os.getpid()), file=sys.stderr)
traceback.print_exc() traceback.print_exc()
_ = exc _.ret = None
_.exc = exc
cout.send(_) cout.send(_)
cout.close() cout.close()
...@@ -100,11 +103,12 @@ class SubProcess(object): ...@@ -100,11 +103,12 @@ class SubProcess(object):
def exitcode(proc): def exitcode(proc):
return proc.popen.returncode return proc.popen.returncode
# join waits for the subprocess to end. # join waits for the subprocess to end and returns or raises its result.
def join(proc, ctx): def join(proc, ctx): # -> any | exception
gotend = False gotend = False
goteof = False goteof = False
joined = False joined = False
end = None
while not (goteof and joined): while not (goteof and joined):
if ctx.err() is not None: if ctx.err() is not None:
raise ctx.err() raise ctx.err()
...@@ -124,10 +128,16 @@ class SubProcess(object): ...@@ -124,10 +128,16 @@ class SubProcess(object):
else: else:
if ok: if ok:
if not gotend: if not gotend:
assert _ == 'END' assert isinstance(_, _END)
gotend = True gotend = True
end = _
else: else:
raise AssertionError("got %r after END" % (_,)) raise AssertionError("got %r after END" % (_,))
if not gotend:
return None
if end.exc is not None:
raise end.exc
return end.ret
# send sends object to subprocess input. # send sends object to subprocess input.
def send(proc, obj): def send(proc, obj):
...@@ -152,3 +162,9 @@ class SubProcess(object): ...@@ -152,3 +162,9 @@ class SubProcess(object):
if isinstance(_, BaseException): if isinstance(_, BaseException):
raise _ raise _
return _, True return _, True
class _END:
# .ret any | None
# .exc Exception | None
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment