My PC was Slow as Molasses: The Culprit? Orphaned `grep` Processes After a Shell Timeout.
Hey there, oji_ai_dev here. Working on AI agents and bots as a side hustle often brings a different flavor of technical challenge compared to my day job. This time, my development PC suddenly ground to a halt, and I spe
Hey there, oji_ai_dev here.
Working on AI agents and bots as a side hustle often brings a different flavor of technical challenge compared to my day job. This time, my development PC suddenly ground to a halt, and I spent several hours debugging the issue.
Long story short, the culprit wasn't Windows Defender (though it looked like it) but rather a bunch of "orphaned grep processes" hiding behind it.
The Symptom: PC Stuck at 100% CPU Usage
One evening, as I was setting up my dev environment and coding, my PC's fans suddenly started roaring. Typing in VSCode became sluggish, almost unworkable. Clearly, something was very wrong.
I opened Task Manager, and sure enough, the CPU usage was pegged at 100%. At the top of the list was the familiar MsMpEng.exe – Windows Defender.
"Not you again..."
Any developer has probably experienced this. When you generate or read a large number of files, Defender's real-time scanning can go haywire and bring your PC to its knees. "Oh, it's just one of those days," I thought, and temporarily disabled Defender.
...But the situation didn't change. CPU was still at 100%. This was bad.
The Investigation: The Real Culprit Behind Defender
If Defender wasn't the culprit, what was eating up all that CPU? Staring at the Task Manager's "Details" tab, and looking at the processes consuming CPU time, I noticed several unfamiliar processes:
grep.exe
Why was this here? And multiple instances of it? This was GNU grep bundled with Git for Windows. I didn't remember starting it directly.
Then, I recalled my actions just prior. I had used an AI assistant (Claude) to search the contents of a massive monorepo. This repository was a chaotic mess of accumulated logs and build artifacts from years of operation, totaling about 34GB.
The command I fed to the AI assistant was something simple, like this:
grep -r "some_legacy_function" .
The shell environment used by the AI assistant is configured to time out after a certain period (e.g., 300 seconds) for safety. Most likely, searching such a huge repository took too long, and the parent shell died due to a timeout.
Here's where the problem started.
In a Linux environment, when a parent shell dies, its child processes often terminate along with it. However, grep.exe running within Git Bash on Windows behaved differently. Even after its parent was gone, the child processes continued to run.
These are "orphan processes."
Multiple grep.exe instances, having lost their parent, continued to relentlessly scan 34GB of files, unmanaged. No wonder the CPU was at 100%. What appeared to be Defender going berserk was merely a secondary phenomenon: these orphaned processes were generating an insane amount of file I/O, and Defender's scan was reacting to it. I had completely misidentified the root cause.
The Fix and Prevention
Once the cause was known, the fix was simple. I manually force-terminated all suspicious grep.exe processes from Task Manager. The roaring noise immediately subsided, and my PC quieted down, with CPU usage dropping to around 5%. Peace was restored.
However, this left me vulnerable to the same mistake again. A more fundamental solution was needed.
First, I decided to stop indiscriminately using grep -r on huge repositories. It completely ignores .gitignore and diligently searches through node_modules, large binaries, and everything else, which is terrible for performance. Instead, I've standardized on ripgrep (rg), which intelligently searches while respecting .gitignore and is much faster.
Furthermore, I decided to implement a hook in my AI assistant's execution environment to prevent potentially dangerous commands from being run in the first place. This simple mechanism checks the command's content before the tool (in this case, Bash) is executed, and if it matches certain patterns, it throws an error and stops.
The concept is a script similar to this:
// .claude/hooks/block_recursive_grep.js (conceptual hook script)
const tool = process.env.CLAUDE_TOOL_NAME;
const params = JSON.parse(process.env.CLAUDE_TOOL_PARAMS);
if (tool === 'Bash') {
const command = params.command;
// Define dangerous command patterns that trigger recursive searches
const recursivePatterns = [
/grep\s+.*\s-r\b/, // grep -r
/grep\s+.*\s--recursive\b/, // grep --recursive
/find\s+.*\s\|\s*xargs\s+grep/, // find | xargs grep
/findstr\s+.*\s\/s\b/ // findstr /s (Windows)
];
// If any pattern matches, block the command and exit with an error
if (recursivePatterns.some(p => p.test(command))) {
console.error(`ERROR: Recursive grep is blocked due to performance risk on large repos. Use the 'Grep' tool (ripgrep) instead, which respects .gitignore and is much faster.`);
process.exit(1); // Block the command
}
}
process.exit(0); // Allow other commands
With this hook in place, if I accidentally tell the AI to use grep -r in the future, it will be blocked before execution and prompted to "use ripgrep instead because it's dangerous." For someone as forgetful as me, these kinds of physical guardrails are the most effective.
Summary
I learned two main lessons from this incident:
- Shell timeouts don't guarantee child processes will be killed. Especially in Windows environments, it's crucial to be aware of the risk of orphaned processes consuming resources.
- Don't be fooled by superficial symptoms (like Defender running wild). Always suspect that there might be a true culprit generating massive I/O behind the scenes.
Time for side projects is limited, so losing half a day to environment issues like this is truly painful. But every failure makes my environment more robust. I hope this incident log helps save someone else's precious time. 👍
I build and run small Python systems — trading bots, RAG APIs, scheduled automation — and write up whatever breaks along the way.
If a provider-agnostic RAG Q&A API is useful to you, mine is MIT-licensed on GitHub: rag-faq-api. It runs and passes its full test suite **with no API key* (offline stub LLM + hashing embedder), swaps to Claude / Gemini / OpenAI via one env var, and ships a retrieval-quality harness (Hit@k / MRR / Recall@k) with a chunking sweep.*
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.