Diagnosing cPanel cpsrvd Daemon Crashes, eximstats MySQL Bloat & Exim Queue Pile-Up Causing WordPress 500 Errors
One of the most insidious failure chains in shared and semi-dedicated cPanel/WHM hosting occurs silently over days or weeks until the server collapses under its own weight. The symptoms look unrelated: the cPanel interface becomes sluggish or inaccessible, WordPress sites start returning HTTP 500 errors, MySQL queries slow to a crawl, and email stops flowing. Sysadmins often chase four separate rabbit holes when in reality a single upstream problem — eximstats MySQL table bloat — is the source of all the downstream chaos.
This article documents the full diagnostic chain, real log evidence, and remediation commands for this multi-system failure scenario.
The Failure Chain — How One Table Destroys a Server
eximstats DB grows unchecked (50 GB+)
↓
MySQL I/O saturation → all queries slow
↓
cpsrvd daemon timeouts waiting on MySQL → cPanel UI becomes unavailable
↓
Exim mail queue backs up (no stats logging) → queue floods RAM
↓
PHP memory exhausted → WordPress returns HTTP 500
Understanding this causal chain is critical. Let’s trace every step.
Step 1: Recognize the Warning Signs
Symptom A — cPanel/WHM interface is slow or timing out
WHM → Main >> WHM
Error: Error from cpserver: Error executing "session_init": Connection refused
Or logging into cPanel presents a blank page or “cpsrvd timed out” message.
Symptom B — WordPress 500 Errors
Check the Apache/LiteSpeed error log:
tail -n 100 /usr/local/apache/logs/error_log
You’ll see entries like:
[Wed Sep 24 04:12:33.102183 2026] [core:notice] [pid 4421] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
[Wed Sep 24 04:12:34.221892 2026] [cgi:error] [pid 8832] AH01215: /usr/local/cpanel/cgi-sys/php81: (2)No such file or directory
[Wed Sep 24 04:12:41.009001 2026] [:error] [pid 9001] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /home/USER/public_html/wp-includes/class-wp-hook.php on line 303
The PHP memory exhaustion is a downstream symptom — MySQL is too slow to respond to WordPress DB queries within the PHP max_execution_time, causing query pile-up and memory inflation.
Symptom C — Disk Space Disappearing
df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 200G 194G 6.0G 97% /
du -sh /var/lib/mysql/eximstats/
58G /var/lib/mysql/eximstats/
There it is. The eximstats database directory alone is consuming 58 GB.
Step 2: Confirm the MySQL I/O Bottleneck
Check MySQL process list for blocking queries
mysql -u root -e "SHOW FULL PROCESSLIST\G" | grep -A5 eximstats
You’ll likely see:
*************************** 7. row ***************************
Id: 4421
User: cpanellogd
Host: localhost
db: eximstats
Command: Query
Time: 312
State: Waiting for table metadata lock
Info: INSERT INTO smtp (user, host, sender, sendunixtime, msgid, ...
A cpanellogd process has been waiting 312 seconds to INSERT into the smtp table. This is the log daemon that records Exim delivery data. When the table is massive and unindexed-beyond-capacity, INSERTs take minutes.
Verify table sizes inside MySQL
mysql -u root -e "
SELECT table_name,
ROUND(((data_length + index_length) / 1024 / 1024 / 1024), 2) AS size_gb
FROM information_schema.TABLES
WHERE table_schema = 'eximstats'
ORDER BY size_gb DESC;
"
Expected output on a bloated system:
+------------+---------+
| table_name | size_gb |
+------------+---------+
| smtp | 42.18 |
| sends | 12.07 |
| failures | 2.94 |
| defers | 0.98 |
+------------+---------+
The smtp table at 42 GB is the primary offender. It stores one row per accepted SMTP delivery event — with no automatic TTL pruning unless the cpanellogd service’s housekeeping is running. If cpanellogd was previously crashed or killed, the backlog never gets pruned.
Step 3: Diagnose the cpsrvd Crash
grep -i "timeout\|error\|died\|crash\|mysql\|refused" /usr/local/cpanel/logs/error_log | tail -50
Typical output:
[2026-09-23 22:41:12 -0500] info [cpsrvd] Worker (pid 18923) exited with signal 11 (Segmentation fault)
[2026-09-23 22:41:15 -0500] warn [cpsrvd] Too many worker failures; restarting entire daemon
[2026-09-23 22:41:22 -0500] error [cpsrvd] MySQL connection failed: Lost connection to MySQL server during query
[2026-09-23 22:41:22 -0500] error [session_init] Cannot connect to database: DBI connect('database=eximstats'...) failed: Lost connection to MySQL server
cpsrvd is segfaulting because the MySQL eximstats connection hangs so long that it overruns the worker’s internal timeout, triggering abnormal termination. After several worker failures, the entire daemon restarts — making cPanel/WHM appear as “down” for 30–60 second windows repeatedly.
Step 4: Examine the Exim Mail Queue Flood
When cpanellogd blocks on MySQL, Exim continues accepting mail but cannot log deliveries. Deferred and frozen messages accumulate:
exim -bpc
14,839
Nearly 15,000 messages in queue. Investigate the senders:
exim -bp | awk '{print $4}' | sort | uniq -c | sort -rn | head -20
4821 <[email protected]>
3104 <>
2089 <[email protected]>
1099 <[email protected]>
The first two entries are red flags:
[email protected]— a potentially compromised cPanel account sending spam<>— bounce messages (NDRs) generated in response to spam that forged your server’s address (backscatter)
Identify the compromised WordPress installation sending spam
exim -bp | grep compromised-domain | head -5 | awk '{print $3}' | xargs -I{} exim -Mvh {}
Look at the X-PHP-Originating-Script header (added by cPanel’s PHP mail handler):
X-PHP-Originating-Script: 1004:wp-includes/class-phpmailer.php
# Find which WordPress site belongs to UID 1004
id 1004
# uid=1004(clientuser) gid=1004(clientuser) groups=1004(clientuser)
ls /home/clientuser/public_html/wp-content/plugins/ | grep -i contact
Often you’ll find a vulnerable contact form plugin generating spam programmatically.
Step 5: Emergency Remediation
5.1 — Immediately throttle the Exim queue to stop RAM saturation
# Freeze all messages currently in queue (stops delivery attempts, reduces I/O)
exiqgrep -i | xargs exim -Mf
# Count frozen messages
exim -bpc
5.2 — Purge the eximstats database (the root fix)
Option A: Use the official cPanel script (recommended)
/usr/local/cpanel/bin/eximstats_db.pl --purge
This deletes records older than the retention threshold. On a heavily bloated DB it may run for 20–40 minutes. Monitor:
watch -n5 'mysql -u root -e "SHOW FULL PROCESSLIST\G" | grep -c eximstats'
Option B: Manual truncation (immediate, loses all historical stats)
mysql -u root eximstats -e "
TRUNCATE TABLE sends;
TRUNCATE TABLE smtp;
TRUNCATE TABLE failures;
TRUNCATE TABLE defers;
"
Warning:
TRUNCATEis non-recoverable. If you need historical email statistics for abuse reporting or client SLA evidence, dump the data first:mysqldump -u root eximstats smtp > /root/eximstats_smtp_backup_$(date +%F).sql gzip /root/eximstats_smtp_backup_$(date +%F).sql
Option C: Drop and recreate the database (cleanest)
mysqldump -u root eximstats > /root/eximstats_full_backup.sql
mysql -u root -e "DROP DATABASE eximstats;"
/usr/local/cpanel/scripts/eximstats_db
The last command is cPanel’s own schema initializer — it will recreate eximstats with the correct table structure and indexes.
5.3 — Reclaim disk space with OPTIMIZE TABLE
After truncation, the .ibd file on disk won’t shrink immediately. Run:
mysql -u root eximstats -e "OPTIMIZE TABLE sends, smtp, failures, defers;"
Then verify disk reclamation:
du -sh /var/lib/mysql/eximstats/
df -h /var/lib/mysql/
5.4 — Restart cpsrvd and verify
/usr/local/cpanel/scripts/restartsrv_cpsrvd
Wait 10 seconds then confirm:
ps aux | grep cpsrvd | grep -v grep
tail -n 20 /usr/local/cpanel/logs/error_log
Expected clean output:
[2026-09-24 06:05:01 -0500] info [cpsrvd] cPanel/WHM (build 11.120.0.10) - [PID: 19201] is now listening
5.5 — Unfreeze and process (or purge) the mail queue
# Process legitimate frozen messages
exiqgrep -iz | xargs exim -Mt
# Or — if the queue is predominantly spam/backscatter, nuke it:
exiqgrep -iz | xargs exim -Mrm
# Remove messages from the confirmed spam sender:
exiqgrep -f '[email protected]' -i | xargs exim -Mrm
5.6 — Lock down the compromised WordPress account
# Immediately suspend the cPanel account to stop outbound spam
whmapi1 suspendacct user=clientuser reason="Spam_investigation"
# Change all WordPress salts and reset the wp-config.php keys
cd /home/clientuser/public_html
wp config shuffle-salts --allow-root
# Scan for PHP backdoors/webshells
find /home/clientuser/public_html -name "*.php" -newer /home/clientuser/public_html/wp-config.php \
-exec grep -l "eval\|base64_decode\|gzuncompress\|assert" {} \;
Step 6: Prevent Recurrence
6.1 — Automate eximstats purging via cron
crontab -e -u root
Add:
# Purge eximstats daily at 2 AM to prevent bloat
0 2 * * * /usr/local/cpanel/bin/eximstats_db.pl --purge >> /var/log/eximstats_purge.log 2>&1
6.2 — Cap eximstats retention in WHM
Navigate to WHM → Server Configuration → Statistics Software Configuration and reduce:
- Maximum Age for Exim Log Parsing:
30 days(default is often 90+) - Disable Exim Disk Usage Stats if you don’t use them in AWStats
6.3 — Set up MySQL disk-space alerting
cat > /etc/cron.hourly/mysql-diskspace-alert << 'EOF'
#!/bin/bash
THRESHOLD=80
USAGE=$(df /var/lib/mysql | awk 'NR==2{print $5}' | tr -d '%')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
echo "ALERT: MySQL partition at ${USAGE}% on $(hostname)" | \
mail -s "MySQL Disk Alert" root@localhost
fi
EOF
chmod +x /etc/cron.hourly/mysql-diskspace-alert
6.4 — Enable LiteSpeed or CSF/LFD rate limiting for outbound mail
If using ConfigServer Firewall (CSF) — which ships with most cPanel servers — add per-account outbound SMTP rate limiting:
# Edit CSF config
nano /etc/csf/csf.conf
Set:
# Maximum outbound SMTP connections per user per hour
SMTP_BLOCK = 1
SMTP_ALLOWUSER = root
Restart CSF:
csf -r
6.5 — Implement Exim queue monitoring with a Nagios-compatible check
cat > /usr/local/bin/check_exim_queue << 'EOF'
#!/bin/bash
QUEUE_SIZE=$(exim -bpc)
WARN=500
CRIT=2000
if [ "$QUEUE_SIZE" -ge "$CRIT" ]; then
echo "CRITICAL: Exim queue has $QUEUE_SIZE messages"
exit 2
elif [ "$QUEUE_SIZE" -ge "$WARN" ]; then
echo "WARNING: Exim queue has $QUEUE_SIZE messages"
exit 1
else
echo "OK: Exim queue has $QUEUE_SIZE messages"
exit 0
fi
EOF
chmod +x /usr/local/bin/check_exim_queue
Step 7: Restore WordPress — Fixing the 500 Errors
Once MySQL I/O pressure is relieved and disk space is recovered, the WordPress 500 errors should self-resolve on the next page load. Verify by:
# Enable WP_DEBUG temporarily
wp config set WP_DEBUG true --raw --allow-root --path=/home/clientuser/public_html
wp config set WP_DEBUG_LOG true --raw --allow-root --path=/home/clientuser/public_html
# Tail the debug log
tail -f /home/clientuser/public_html/wp-content/debug.log
If errors persist, check for a corrupted .htaccess:
cd /home/clientuser/public_html
mv .htaccess .htaccess.bak
wp rewrite flush --allow-root
Check the PHP memory limit is sufficient:
php -r "echo ini_get('memory_limit');"
# Should return at least 256M for WooCommerce, 512M for LMS sites
Override via .user.ini if WHM MultiPHP settings aren’t propagating fast enough:
echo "memory_limit = 512M" > /home/clientuser/public_html/.user.ini
Infrastructure Note: Why This Happens More on Shared Servers
This failure chain disproportionately affects shared hosting environments where multiple WordPress sites, Exim, MySQL, and cPanel’s own daemons are all competing for the same MySQL instance. The key architectural problem is that eximstats has no inherent self-limiting mechanism — it will grow indefinitely until manually pruned or a cron job is configured.
On high-traffic cPanel servers handling dozens of WordPress installations, the smtp table can grow by 1–3 GB per week under normal email volume. After 90 days without pruning, a 50–100 GB table is realistic.
If you’re managing multiple WordPress sites on a cPanel VPS and finding this scenario recurring, you should consider migrating to Dedicated Servers where MySQL can be isolated to a dedicated SSD partition completely separate from OS and Exim log storage — eliminating the disk-space competition entirely. For teams operating within Pakistan, Dedicated Servers in Pakistan offer low-latency local hosting with full root access so you can implement the preventive measures in this guide without restrictions from a shared environment.
Full Remediation Checklist
| Step | Command / Action | Priority |
|---|---|---|
| Check disk usage | du -sh /var/lib/mysql/eximstats/ |
⚠️ Immediate |
| Confirm MySQL blocking | SHOW FULL PROCESSLIST\G |
⚠️ Immediate |
| Freeze Exim queue | exiqgrep -i | xargs exim -Mf |
⚠️ Immediate |
| Backup eximstats | mysqldump -u root eximstats > backup.sql |
✅ Before purge |
| Truncate eximstats | TRUNCATE TABLE smtp, sends, failures, defers |
✅ Root fix |
| OPTIMIZE TABLE | OPTIMIZE TABLE smtp, sends... |
✅ Disk reclaim |
| Restart cpsrvd | /usr/local/cpanel/scripts/restartsrv_cpsrvd |
✅ UI restore |
| Purge spam queue | exiqgrep -f 'spammer' -i | xargs exim -Mrm |
✅ Mail restore |
| Suspend spam account | whmapi1 suspendacct user=X |
✅ Security |
| Add purge cron | 0 2 * * * .../eximstats_db.pl --purge |
🔁 Prevention |
| Set retention limits | WHM → Statistics Software Config | 🔁 Prevention |
Conclusion
The eximstats MySQL bloat → cpsrvd crash → WordPress 500 failure chain is one of the most under-documented cascading failures in cPanel hosting. Because each symptom superficially resembles an independent problem, sysadmins often waste hours troubleshooting WordPress plugins, .htaccess rules, or PHP settings before discovering a 50 GB database table sitting quietly at the root of everything.
The diagnostic path is methodical: disk → MySQL table sizes → process list → log files → Exim queue. Once you know the pattern, the entire resolution takes under 30 minutes. Prevention requires a single cron job and a WHM retention tweak.
Set it, schedule it, and monitor it — before the next 3 AM emergency call.
