Skip to content

Commit 27b066f

Browse files
committed
fix(runserver): don't capture watch subprocess stdout
Both ProcessManager and MultiWatchProcessManager spawned the Tailwind CLI watch subprocess with `stdout=PIPE, stderr=STDOUT` but never read from the pipe — the monitor loop only polls process state. Once the OS pipe buffer (~64 KB on Linux) fills up, the watcher blocks on its next write and silently stops rebuilding, which is exactly the symptom you'd never suspect in a long dev session. Drop the stdout/stderr overrides (and the now-unnecessary bufsize=1) so the watch subprocess inherits the parent streams. The watch output now flows straight to the terminal — a UX improvement on top of the deadlock fix, because the user can finally see rebuild progress during `tailwind runserver`.
1 parent 3587802 commit 27b066f

1 file changed

Lines changed: 7 additions & 7 deletions

File tree

src/django_tailwind_cli/management/commands/tailwind.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,14 +1043,14 @@ def start_concurrent_processes(self, watch_cmd: list[str], server_cmd: list[str]
10431043
signal.signal(signal.SIGTERM, self._signal_handler)
10441044

10451045
try:
1046-
# Start Tailwind watch process
1046+
# Start Tailwind watch process — inherit stdout/stderr so the
1047+
# user sees watch output live and we avoid a pipe-fill deadlock:
1048+
# the OS pipe buffer (~64 KB on Linux) would otherwise fill up
1049+
# after a few minutes of rebuilds and block the watcher.
10471050
watch_process = subprocess.Popen(
10481051
watch_cmd,
10491052
cwd=settings.BASE_DIR,
1050-
stdout=subprocess.PIPE,
1051-
stderr=subprocess.STDOUT,
10521053
text=True,
1053-
bufsize=1, # Line buffered
10541054
)
10551055
self.processes.append(watch_process)
10561056
typer.secho("Started Tailwind CSS watch process", fg=typer.colors.GREEN)
@@ -1141,13 +1141,13 @@ def start_watch_processes(self, config: Config, *, verbose: bool = False) -> Non
11411141
typer.secho(f"🚀 Starting watch for '{entry.name}'...", fg=typer.colors.CYAN)
11421142
typer.secho(f" • Command: {' '.join(watch_cmd)}", fg=typer.colors.BLUE)
11431143

1144+
# Inherit stdout/stderr so output flows to the terminal and we
1145+
# avoid a pipe-fill deadlock — the OS pipe buffer would otherwise
1146+
# block the watcher after ~64 KB of rebuild status lines.
11441147
process = subprocess.Popen(
11451148
watch_cmd,
11461149
cwd=settings.BASE_DIR,
1147-
stdout=subprocess.PIPE,
1148-
stderr=subprocess.STDOUT,
11491150
text=True,
1150-
bufsize=1,
11511151
)
11521152
self.processes.append(process)
11531153
typer.secho(f"Watching '{entry.name}': {entry.src_css}", fg=typer.colors.GREEN)

0 commit comments

Comments
 (0)