Skip to content

[BUGFIX] Improve PlantumlRenderer robustness and temp file cleanup#1281

Merged
jaapio merged 3 commits into
phpDocumentor:mainfrom
CybotTM:fix/plantuml-renderer-robustness
Jan 18, 2026
Merged

[BUGFIX] Improve PlantumlRenderer robustness and temp file cleanup#1281
jaapio merged 3 commits into
phpDocumentor:mainfrom
CybotTM:fix/plantuml-renderer-robustness

Conversation

@CybotTM

@CybotTM CybotTM commented Jan 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #1279 addressing code review findings for improved robustness.

Changes

1. Race-safe directory creation (lines 57, 112-130)

  • Extracted ensureDirectoryExists() helper method with clear documentation
  • Handles race conditions where concurrent processes may create the directory
  • Step-by-step logic with comments explaining each check

2. Check tempnam() return value (lines 66-74)

  • tempnam() can return false on failure
  • Now properly checks and logs error before continuing

3. Clean up temporary files (lines 106-107)

  • Deletes .pu source file and .svg output after reading
  • Prevents unbounded disk usage growth during documentation builds

4. Safe test cleanup (test lines 47-53)

  • Multiple guards to prevent accidental deletion of wrong directories
  • Validates temp directory path before cleanup

Files Changed

  • packages/guides-graphs/src/Graphs/Renderer/PlantumlRenderer.php
  • packages/guides-graphs/tests/unit/Renderer/PlantumlRendererTest.php

Test Plan

  • PHPUnit test passes
  • PHPStan passes
  • PHPCS passes

Comment thread packages/guides-graphs/tests/unit/Renderer/PlantumlRendererTest.php Outdated
@CybotTM CybotTM force-pushed the fix/plantuml-renderer-robustness branch 3 times, most recently from f1ecc50 to 9258580 Compare January 7, 2026 13:30
@CybotTM

CybotTM commented Jan 7, 2026

Copy link
Copy Markdown
Contributor Author

sorry for the noise, should be fine now.


if (!is_dir($this->tempDirectory)) {
mkdir($this->tempDirectory, 0o755, true);
if (!is_dir($this->tempDirectory) && !@mkdir($this->tempDirectory, 0o755, true) && !is_dir($this->tempDirectory)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to split the conditions here. And not to perform operations in an condition like mkdir those are very hard to detect, people do not expect them in there.
Also the !is_dir($this->tempDirectory) is performed twice, that seems to be invalid.

@CybotTM CybotTM Jan 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a simple trinary operation, not so uncommon/unknown, and the duplicated is_dir() is intentionally, that's the whole point of it.

if (!is_dir($this->tempDirectory)) {

    // 2. Attempt Creation: Try to create it with 0755 permissions.
    // The '@' suppresses a PHP warning if it fails.
    // 'true' allows recursive creation of parent folders.
    $creationSuccessful = @mkdir($this->tempDirectory, 0755, true);

    if (!$creationSuccessful) {
        
        // 3. Final Verification (Race Condition Check):
        // If mkdir failed, it might be because another process 
        // created it between step 1 and step 2.
        if (!is_dir($this->tempDirectory)) {
            
            // IF IT STILL DOESN'T EXIST: Handle the real failure.
            // This is where you would place your error logic or throw an exception.
            throw new \Exception("Failed to create directory: " . $this->tempDirectory);
        }
    }
}

But this is already explained in the PR description.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get it's common to do this, but I do see it as a bad practice to combine things like this. It makes the code hard to understand.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get it's common to do this, but I do see it as a bad practice to combine things like this. It makes the code hard to understand.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already changed it. You may notice.

@CybotTM CybotTM changed the title [BUGFIX] Improve PlantumlRenderer robustness and cleanup [BUGFIX] Improve PlantumlRenderer robustness and temp file cleanup Jan 8, 2026
CybotTM and others added 3 commits January 18, 2026 20:20
- Handle mkdir race condition with triple-check pattern
- Check tempnam() return value for false
- Clean up temporary .pu and .svg files after rendering
- Fix test cleanup to delete files before rmdir
Replace dangerous glob-based cleanup with safe removeTempDirSafely():
- Validates directory is under system temp using realpath()
- Validates directory has expected 'plantuml-test-' prefix
- Uses RecursiveIteratorIterator for proper recursive deletion

Addresses review feedback about potential catastrophic deletion
if $tempDir variable were to be empty or corrupted.
Addresses review feedback: the race-safe mkdir pattern is now
in a dedicated method with clear documentation, making the
intent more readable.
@jaapio jaapio force-pushed the fix/plantuml-renderer-robustness branch from 9cf7aa2 to db41968 Compare January 18, 2026 19:20
@jaapio jaapio enabled auto-merge January 18, 2026 19:20
@jaapio jaapio merged commit 8acd95a into phpDocumentor:main Jan 18, 2026
58 checks passed
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