# 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. Use when this capability is needed.

- Skill: `tomevault-io/find-resource-leaks` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/find-resource-leaks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/find-resource-leaks/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/find-resource-leaks

---


# Resource Leak Detection

Analyze PHP code for resource leak issues.

## Detection Patterns

### 1. Unclosed File Handles

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```php
// 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

```bash
# 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

```php
$resource = acquire();
try {
    process($resource);
} finally {
    release($resource);
}
```

### Use Context Managers (PHP 8.1+)

```php
// Custom destructor-based cleanup
$file = new FileHandler($path);
// Automatically closed on unset/scope exit
```

### Use Transactions Properly

```php
$connection->beginTransaction();
try {
    $this->process();
    $connection->commit();
} catch (Throwable $e) {
    $connection->rollBack();
    throw $e;
}
```

## Output Format

```markdown
### 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:**
```php
// With proper cleanup
```
```

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/dykyi-roman) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-11 -->

