Awesome-claude-code find-resource-leaks
Detects resource leaks in PHP code. Finds unclosed file handles, database connections not released, streams not freed, missing finally blocks, temporary files not cleaned.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/find-resource-leaks" ~/.claude/skills/dykyi-roman-awesome-claude-code-find-resource-leaks && rm -rf "$T"
manifest:
skills/find-resource-leaks/SKILL.mdsource content
Resource Leak Detection
Analyze PHP code for resource leak issues.
Detection Patterns
1. Unclosed File Handles
// BUG: File handle not closed $file = fopen('data.txt', 'r'); $content = fread($file, filesize('data.txt')); // Missing: fclose($file); // BUG: Early return without close $file = fopen($path, 'w'); if (!$valid) { return false; // File handle leaked } fwrite($file, $data); fclose($file);
2. Database Connections Not Released
// BUG: Connection not closed $pdo = new PDO($dsn, $user, $pass); $stmt = $pdo->query($sql); // PDO not unset, may hold connection // BUG: In connection pool context $connection = $pool->acquire(); $result = $connection->query($sql); if ($error) { throw new Exception(); // Connection leaked } $pool->release($connection);
3. Streams Not Freed
// BUG: Stream not closed $stream = fopen('php://temp', 'r+'); fwrite($stream, $data); // Missing: fclose($stream); // BUG: cURL handle not closed $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); // Missing: curl_close($ch);
4. Missing Finally Blocks
// BUG: No finally for cleanup $lock = $this->acquireLock(); try { $this->process(); } catch (Exception $e) { $this->log($e); throw $e; // Lock not released on exception } $this->releaseLock($lock); // FIXED: $lock = $this->acquireLock(); try { $this->process(); } finally { $this->releaseLock($lock); }
5. Temporary Files Not Cleaned
// BUG: Temp file not deleted $tempFile = tempnam(sys_get_temp_dir(), 'prefix_'); file_put_contents($tempFile, $data); $result = $this->processFile($tempFile); // Missing: unlink($tempFile); // BUG: Early return leaves temp file $temp = tmpfile(); if (!$valid) { return null; // Temp file not cleaned }
6. Socket/Network Resources
// BUG: Socket not closed $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_connect($socket, $host, $port); $data = socket_read($socket, 1024); // Missing: socket_close($socket); // BUG: SSH connection not closed $connection = ssh2_connect($host); ssh2_auth_password($connection, $user, $pass); $stream = ssh2_exec($connection, $command); // Resources not freed
7. Image/GD Resources
// BUG: Image resource not destroyed $image = imagecreatefromjpeg($path); $resized = imagescale($image, 100, 100); imagejpeg($resized, $output); // Missing: imagedestroy($image); imagedestroy($resized);
8. Doctrine/ORM Resources
// BUG: Large result set in memory $query = $em->createQuery('SELECT u FROM User u'); $users = $query->getResult(); // All in memory // BUG: Detached entities not cleared foreach ($largeDataset as $data) { $entity = new Entity($data); $em->persist($entity); $em->flush(); // Missing: $em->clear(); for large batches }
Grep Patterns
# fopen without fclose Grep: "fopen\([^)]+\)" --glob "**/*.php" Grep: "fclose\(" --glob "**/*.php" # curl_init without curl_close Grep: "curl_init\(" --glob "**/*.php" Grep: "curl_close\(" --glob "**/*.php" # try without finally Grep: "try\s*\{[^}]+\}\s*catch" --glob "**/*.php" # tempnam/tmpfile usage Grep: "(tempnam|tmpfile)\(" --glob "**/*.php"
Severity Classification
| Pattern | Severity |
|---|---|
| Database connection leak | 🔴 Critical |
| File handle in loop | 🔴 Critical |
| Lock not released | 🔴 Critical |
| Single file handle | 🟠 Major |
| Temp file not cleaned | 🟠 Major |
| Image resource | 🟡 Minor |
Best Practices
Use try-finally
$resource = acquire(); try { process($resource); } finally { release($resource); }
Use Context Managers (PHP 8.1+)
// Custom destructor-based cleanup $file = new FileHandler($path); // Automatically closed on unset/scope exit
Use Transactions Properly
$connection->beginTransaction(); try { $this->process(); $connection->commit(); } catch (Throwable $e) { $connection->rollBack(); throw $e; }
Output Format
### Resource Leak: [Description] **Severity:** 🔴/🟠/🟡 **Location:** `file.php:line` **Type:** [File Handle|Connection|Stream|Lock|Temp File|...] **Issue:** Resource acquired but not properly released. **Code:** ```php // Problematic code
Fix:
// With proper cleanup