Skip to content

fix(format): use communicate rathan than .stdin.write#2966

Closed
prousso wants to merge 1 commit intokoxudaxi:mainfrom
prousso:fix/pipe-buffer-deadlock
Closed

fix(format): use communicate rathan than .stdin.write#2966
prousso wants to merge 1 commit intokoxudaxi:mainfrom
prousso:fix/pipe-buffer-deadlock

Conversation

@prousso
Copy link
Copy Markdown

@prousso prousso commented Jan 19, 2026

to avoid dealocks due to any of the other OS pipe buffers filling
up and blocking the child process

Example that hang:

import subprocess


def apply_ruff_check_and_format(code: str) -> str:
    """Run ruff check and format in a single pipeline for better performance."""
    check_proc = subprocess.Popen(  # noqa: S603
        ["ruff", "check", "--fix", "--unsafe-fixes", "-"],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    format_proc = subprocess.Popen(  # noqa: S603
        ["ruff", "format", "-"],
        stdin=check_proc.stdout,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    if check_proc.stdout:  # pragma: no branch
        check_proc.stdout.close()
    check_proc.stdin.write(code.encode("utf-8"))  # type: ignore[union-attr]
    check_proc.stdin.close()  # type: ignore[union-attr]
    stdout, _ = format_proc.communicate()
    check_proc.wait()
    return stdout.decode("utf-8")


if __name__ == "__main__":
    subprocess.run(["dd", "if=/dev/zero", "of=cactus.py", "bs=65000", "count=1"], check=True)
    with open('cactus.py', 'r') as f:
        code = "".join([line for line in f])
        apply_ruff_check_and_format(code)
``

to avoid dealocks due to any of the other OS pipe buffers filling
up and blocking the child process
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 19, 2026

📝 Walkthrough

Walkthrough

A single-line modification in the ruff code formatter that changes how input is passed to the subprocess check process, switching from direct stdin writing to using the communicate() method.

Changes

Cohort / File(s) Summary
Subprocess Input Handling
src/datamodel_code_generator/format.py
Modified CodeFormatter.apply_ruff_check_and_format to use check_proc.communicate(code.encode(self.encoding)) instead of direct stdin.write() for sending input to ruff check process

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

🐰 A tiny hop, a change so neat,
Where stdin flows in a better beat,
Communicate now takes the lead,
For ruff to process and proceed! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title mentions the main change (using communicate instead of .stdin.write) but contains a typo: 'rathan' should be 'rather'.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@prousso prousso marked this pull request as ready for review January 19, 2026 10:41
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jan 19, 2026

CodSpeed Performance Report

Merging this PR will not alter performance

Comparing prousso:fix/pipe-buffer-deadlock (bba42bb) with main (8c60b1b)

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

Summary

✅ 11 untouched benchmarks
⏩ 98 skipped benchmarks1

Footnotes

  1. 98 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@koxudaxi
Copy link
Copy Markdown
Owner

@prousso
Thank you for creating the PR.
I looked into this and found that switching to communicate() doesn’t actually solve the pipeline deadlock here, because check’s stdout is piped into format’s stdin. communicate() tries to read stdout/stderr in the parent, which conflicts with that pipe (and the parent closes the stdout pipe), so it can still hang or corrupt the stream.
Given that, I have closed this PR and proceed with a safer approach (sequential execution or a properly‑drained pipeline).
Thank you for your supports!!

@github-actions
Copy link
Copy Markdown
Contributor

🎉 Released in 0.54.0

The fix/feature from PR #2967 has been included in this release. See the release notes for details.

Thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants