| 185 | ] = None |
| 186 | |
| 187 | def run(self) -> None: |
| 188 | try: |
| 189 | # Allow subclasses implemented using the "override run()'s body" |
| 190 | # approach to work, by using _run() instead of run(). If that |
| 191 | # doesn't appear to be the case, then assume we're being used |
| 192 | # directly and just use super() ourselves. |
| 193 | # XXX https://github.com/python/mypy/issues/1424 |
| 194 | if hasattr(self, "_run") and callable(self._run): # type: ignore |
| 195 | # TODO: this could be: |
| 196 | # - io worker with no 'result' (always local) |
| 197 | # - tunnel worker, also with no 'result' (also always local) |
| 198 | # - threaded concurrent run(), sudo(), put(), etc, with a |
| 199 | # result (not necessarily local; might want to be a subproc or |
| 200 | # whatever eventually) |
| 201 | # TODO: so how best to conditionally add a "capture result |
| 202 | # value of some kind"? |
| 203 | # - update so all use cases use subclassing, add functionality |
| 204 | # alongside self.exception() that is for the result of _run() |
| 205 | # - split out class that does not care about result of _run() |
| 206 | # and let it continue acting like a normal thread (meh) |
| 207 | # - assume the run/sudo/etc case will use a queue inside its |
| 208 | # worker body, orthogonal to how exception handling works |
| 209 | self._run() # type: ignore |
| 210 | else: |
| 211 | super().run() |
| 212 | except BaseException: |
| 213 | # Store for actual reraising later |
| 214 | self.exc_info = sys.exc_info() |
| 215 | # And log now, in case we never get to later (e.g. if executing |
| 216 | # program is hung waiting for us to do something) |
| 217 | msg = "Encountered exception {!r} in thread for {!r}" |
| 218 | # Name is either target function's dunder-name, or just "_run" if |
| 219 | # we were run subclass-wise. |
| 220 | name = "_run" |
| 221 | if "target" in self.kwargs: |
| 222 | name = self.kwargs["target"].__name__ |
| 223 | debug(msg.format(self.exc_info[1], name)) # noqa |
| 224 | |
| 225 | def exception(self) -> Optional["ExceptionWrapper"]: |
| 226 | """ |