diff --git a/management/univention-join/umc/python/join/__init__.py b/management/univention-join/umc/python/join/__init__.py index 6088a63..96a47f4 100644 --- a/management/univention-join/umc/python/join/__init__.py +++ b/management/univention-join/umc/python/join/__init__.py @@ -40,6 +40,8 @@ import re import dns.resolver import dns.exception +import fcntl +import errno import notifier.threads import apt_pkg @@ -197,13 +199,8 @@ def run(cmd, stepsPerScript, info_handler = _dummyFunc, error_handler = _dummyFu process = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) failedJoinScripts = [] - while True: - # get the next line - line = process.stdout.readline() - if not line: - # no more text from stdout - break - MODULE.process(line.strip()) + def parse(line): + MODULE.process(repr(line.strip()).strip('"\'')) # parse output... first check for errors m = regError.match(line) @@ -214,8 +211,7 @@ def run(cmd, stepsPerScript, info_handler = _dummyFunc, error_handler = _dummyFu # invalid credentials or non existent user # do a critical error, the script will stop here critical_handler(True) - - continue + return # check for currently called join script m = regJoinScript.match(line) @@ -225,14 +221,38 @@ def run(cmd, stepsPerScript, info_handler = _dummyFunc, error_handler = _dummyFu step_handler(stepsPerScript) if 'failed' in line: failedJoinScripts.append(m.groupdict().get('script')) - continue + return # check for other information m = regInfo.match(line) if m: info_handler(m.groupdict().get('message')) step_handler(stepsPerScript/10) - continue + return + + # make stdout file descriptor of the process non-blocking + fd = process.stdout.fileno() + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + + unfinished_line = '' + while True: + # get the next line + try: + line = process.stdout.read() + except IOError as exc: + if exc.errno == errno.EAGAIN: + continue + raise + + if not line: + break # no more text from stdout + + unfinished_line = '' if line.endswith('\n') else '%s%s' % (unfinished_line, line.rsplit('\n', 1)[-1]) + for line in line.splitlines(): + parse(line) + if unfinished_line: + parse(unfinished_line) # get all remaining output stdout, stderr = process.communicate()