Skip to content

Commit

Permalink
Create workers in thread-safe way.
Browse files Browse the repository at this point in the history
Previously you couldn't call a threaded worker from another threaded worker because creating a worker was not thread safe (see #3472). However, the second threaded worker could already be called with self.call_from_thread, so we bake that in.
  • Loading branch information
rodrigogiraoserrao committed Oct 25, 2023
1 parent 34fb596 commit 890b475
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/textual/_work_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from __future__ import annotations

import threading
from functools import partial, wraps
from inspect import iscoroutinefunction
from typing import TYPE_CHECKING, Callable, Coroutine, TypeVar, Union, cast, overload
Expand Down Expand Up @@ -139,9 +140,16 @@ def decorated(
debug_description = f"{method.__name__}({', '.join(token for token in tokens if token)})"
except Exception:
debug_description = "<worker>"

# If we're creating/running a worker from inside a secondary thread,
# do so in a thread-safe way.
if self.app._thread_id != threading.get_ident():
runner = partial(self.app.call_from_thread, self.run_worker)
else:
runner = self.run_worker
worker = cast(
"Worker[ReturnType]",
self.run_worker(
runner(
partial(method, *args, **kwargs),
name=name or method.__name__,
group=group,
Expand Down

0 comments on commit 890b475

Please sign in to comment.