From 9803939a1c3e0ca1811cce2dd763fe7dba52ef39 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sat, 1 Oct 2022 15:47:41 -0700 Subject: [PATCH] replaygain: Fix error handling for parallel runs The parallelism strategy in #3478, in retrospect, used a pretty funky way to deal with exceptions in the asynchronous work---since `apply_async` has an `error_callback` parameter that's meant for exactly this. The problem is that the wrapped function would correctly log the exception *and then return `None`*, confusing any downstream code. Instead of just adding `None`-awareness to the callback, let's just avoid running the callback altogether in the case of an error. --- beetsplug/replaygain.py | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index c228f74b3..63d927f61 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -1085,7 +1085,7 @@ class ExceptionWatcher(Thread): try: exc = self._queue.get_nowait() self._callback() - raise exc[1].with_traceback(exc[2]) + raise exc except queue.Empty: # No exceptions yet, loop back to check # whether `_stopevent` is set @@ -1338,23 +1338,16 @@ class ReplayGainPlugin(BeetsPlugin): def _apply(self, func, args, kwds, callback): if self._has_pool(): - def catch_exc(func, exc_queue, log): - """Wrapper to catch raised exceptions in threads + def handle_exc(exc): + """Handle exceptions in the async work. """ - def wfunc(*args, **kwargs): - try: - return func(*args, **kwargs) - except ReplayGainError as e: - log.info(e.args[0]) # log non-fatal exceptions - except Exception: - exc_queue.put(sys.exc_info()) - return wfunc + if isinstance(exc, ReplayGainError): + self._log.info(exc.args[0]) # Log non-fatal exceptions. + else: + self.exc_queue.put(exc) - # Wrap function and callback to catch exceptions - func = catch_exc(func, self.exc_queue, self._log) - callback = catch_exc(callback, self.exc_queue, self._log) - - self.pool.apply_async(func, args, kwds, callback) + self.pool.apply_async(func, args, kwds, callback, + error_callback=handle_exc) else: callback(func(*args, **kwds))