diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-09-23 12:16:14 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-09-23 12:27:01 +0100 |
commit | 032190aac31604d37740d8aecf6e74a5448de358 (patch) | |
tree | 59a44ea524bfeb422854620f2b46ad811b6c439c | |
parent | df89e37c33e4398a5f8ece9a8b973be3fe2ff361 (diff) | |
download | bitbake-032190aac31604d37740d8aecf6e74a5448de358.tar.gz |
build: Fix log flushing race
There is a race between sending the TaskFailed event which could trigger
the UI to look at the logs and flushing and closing the log files.
Reverse the order of the finally clause and the exception handling
to ensure we've handled the logfiles before sending the task events.
This should fix a race seen in bblogging.BitBakeLogging.test_python_exit_logging
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | lib/bb/build.py | 76 |
1 files changed, 38 insertions, 38 deletions
diff --git a/lib/bb/build.py b/lib/bb/build.py index 99954b0c2..7e4ab9f64 100644 --- a/lib/bb/build.py +++ b/lib/bb/build.py @@ -686,51 +686,51 @@ def _exec_task(fn, task, d, quieterr): try: try: event.fire(TaskStarted(task, fn, logfn, flags, localdata), localdata) - except (bb.BBHandledException, SystemExit): - return 1 - try: for func in (prefuncs or '').split(): exec_func(func, localdata) exec_func(task, localdata) for func in (postfuncs or '').split(): exec_func(func, localdata) - except bb.BBHandledException: - event.fire(TaskFailed(task, fn, logfn, localdata, True), localdata) - return 1 - except (Exception, SystemExit) as exc: - if quieterr: - event.fire(TaskFailedSilent(task, fn, logfn, localdata), localdata) - else: - errprinted = errchk.triggered - # If the output is already on stdout, we've printed the information in the - # logs once already so don't duplicate - if verboseStdoutLogging: - errprinted = True - logger.error(repr(exc)) - event.fire(TaskFailed(task, fn, logfn, localdata, errprinted), localdata) - return 1 - finally: - sys.stdout.flush() - sys.stderr.flush() - - bblogger.removeHandler(handler) - - # Restore the backup fds - os.dup2(osi[0], osi[1]) - os.dup2(oso[0], oso[1]) - os.dup2(ose[0], ose[1]) - - # Close the backup fds - os.close(osi[0]) - os.close(oso[0]) - os.close(ose[0]) + finally: + # Need to flush and close the logs before sending events where the + # UI may try to look at the logs. + sys.stdout.flush() + sys.stderr.flush() + + bblogger.removeHandler(handler) + + # Restore the backup fds + os.dup2(osi[0], osi[1]) + os.dup2(oso[0], oso[1]) + os.dup2(ose[0], ose[1]) + + # Close the backup fds + os.close(osi[0]) + os.close(oso[0]) + os.close(ose[0]) + + logfile.close() + if os.path.exists(logfn) and os.path.getsize(logfn) == 0: + logger.debug2("Zero size logfn %s, removing", logfn) + bb.utils.remove(logfn) + bb.utils.remove(loglink) + except bb.BBHandledException: + event.fire(TaskFailed(task, fn, logfn, localdata, True), localdata) + return 1 + except (Exception, SystemExit) as exc: + if quieterr: + event.fire(TaskFailedSilent(task, fn, logfn, localdata), localdata) + else: + errprinted = errchk.triggered + # If the output is already on stdout, we've printed the information in the + # logs once already so don't duplicate + if verboseStdoutLogging: + errprinted = True + logger.error(repr(exc)) + event.fire(TaskFailed(task, fn, logfn, localdata, errprinted), localdata) + return 1 - logfile.close() - if os.path.exists(logfn) and os.path.getsize(logfn) == 0: - logger.debug2("Zero size logfn %s, removing", logfn) - bb.utils.remove(logfn) - bb.utils.remove(loglink) event.fire(TaskSucceeded(task, fn, logfn, localdata), localdata) if not localdata.getVarFlag(task, 'nostamp', False) and not localdata.getVarFlag(task, 'selfstamp', False): |