Short answer: Find the old lsphp processes with ps -C lsphp -o pid,user,etime,stat,pcpu,rss,args --sort=-etime, see what each one is doing with strace -p PID and its open files, then restart only that user’s PHP by creating ~/.lsphp_restart.txt in their home (detached mode) or send kill PID. Use killall lsphp only as a last resort. Prevent repeats with LSAPI_MAX_PROCESS_TIME, a sane max_execution_time, and by fixing the slow script.
Commands checked against the official LiteSpeed documentation (linked below) on 6 October 2026; not yet run on our lab servers (our cPanel lab runs Apache, not LiteSpeed).
Table of Contents
Why lsphp processes pile up
On cPanel, LiteSpeed Enterprise runs PHP through LSAPI in ProcessGroup mode, the default for Apache-style virtual host PHP handlers. Each user gets a parent lsphp process that forks children to serve requests. With detached mode, those PHP processes keep running even when LiteSpeed itself restarts. That is good for uptime, but it also means a plain systemctl restart lsws does not clear a stuck PHP process.
A process looks “stuck” for one of a few reasons:
- A long-running script: imports, backups, heavy reports,
wp-cron.phpdoing too much at once. - Waiting on something outside: a slow remote API, a DNS lookup, an SMTP server that never answers.
- Waiting on the database: a locked table or a long query.
- Waiting on the disk: the process is in state
D(uninterruptible I/O), often on overloaded or network storage. - Waiting on a PHP session lock: several requests from one visitor queue behind the first.
Each of these holds a PHP slot. When a user hits their process limit (or a CloudLinux LVE limit), new requests get 503 errors even though the server is idle.
Find the stuck processes
List lsphp processes, oldest first, with owner, run time and state:
ps -C lsphp -o pid,ppid,user,etime,stat,pcpu,rss,args --sort=-etime | head -30
Things to look for:
ETIMEin hours, or days, for a child process that should finish in seconds.STATD: waiting on disk I/O; killing it will not help until the I/O finishes.STATRwith high%CPUfor a long time: a loop or a heavy job.STATSwith near-zero CPU: waiting on the network, the database or a lock.
Count processes per user to spot the account that is filling up:
ps -C lsphp -o user= | sort | uniq -c | sort -rn | head
See what a process is doing
Before you kill anything, find out which script and what it waits on. This is how you fix the cause rather than kill the same process every day:
PID=12345
ls -l /proc/$PID/cwd # working directory = which site
tr '\0' ' ' < /proc/$PID/cmdline; echo
lsof -p $PID | grep -E "\.php|TCP|\.sock" # open PHP files, network connections, sockets
timeout 15 strace -tt -T -f -p $PID # live system calls for 15 seconds
LiteSpeed’s 503 troubleshooting page also suggests strace -tt -T -f -p <pid> for problem PHP processes. Reading the output:
| strace shows | Likely cause | Where to look next |
|---|---|---|
poll/recvfrom on a TCP socket to port 443 or 80 | Waiting on a remote HTTP API | The plugin or theme making the call; set a timeout |
poll/read on a MySQL socket | Waiting on a query | mariadb -e "SHOW FULL PROCESSLIST" |
flock on a sess_ file | PHP session lock | The script holding the session open |
| Nothing for a long time, state D | Disk or NFS I/O | iostat -x 2, storage health |
| A fast loop of the same calls | Script loop | The PHP file from lsof |
LiteSpeed’s logs show the server side of the story. Check them for the time the problem started:
tail -n 100 /usr/local/lsws/logs/error.log
tail -n 100 /usr/local/lsws/logs/stderr.log
LiteSpeed lists these log messages among the lsphp-related causes of 503 errors: Reached max children process limit (raise LSAPI_CHILDREN or fix the slow scripts), fork() failed, please increase process limit: Cannot allocate memory (memory or process limits), and Too many open files (file descriptor limit).
Kill or restart safely
Use the narrowest tool that clears the problem.
One process
kill $PID # SIGTERM: lets PHP shut down
sleep 5; ps -p $PID || echo gone
kill -9 $PID # only if it ignored SIGTERM
A process in state D will not die until its I/O returns, even with -9. Fix the storage problem instead.
All PHP for one user (detached mode)
LiteSpeed documents a per-user restart file. Create it in the user’s home directory and LiteSpeed restarts that user’s detached PHP processes:
touch /home/bob/.lsphp_restart.txt
chown bob:bob /home/bob/.lsphp_restart.txt
This is the gentle option for a single account after a php.ini change or a pile-up, and it does not touch other customers.
All PHP on the server
touch /usr/local/lsws/admin/tmp/.lsphp_restart.txt
systemctl restart lsws
In the WebAdmin console the same action is Actions > Restart Detached PHP Processes.
Last resort: killall lsphp ends every PHP process on the server immediately, including requests in the middle of a checkout or a database write. Use it only when the server is unusable, and expect a short burst of errors while PHP restarts.
Stop it happening again
LSAPI environment variables control how long PHP processes may run and idle. The defaults from LiteSpeed’s LSPHP options page:
| Variable | Default | What it controls |
|---|---|---|
LSAPI_MAX_PROCESS_TIME | 3600 s | Longest time a child may spend on one request before it is killed (ProcessGroup and daemon mode) |
LSAPI_MAX_IDLE | 300 s | How long an idle child waits for work before exiting |
LSAPI_PGRP_MAX_IDLE | FOREVER | How long the parent waits with no children before exiting (WebAdmin “Max Idle Time”) |
PHP_LSAPI_CHILDREN | 35 | Maximum children per process group; keep it equal to Max Connections |
PHP_LSAPI_MAX_REQUESTS | 10000 | Requests per child before it exits (limits memory leaks) |
LSAPI_SLOW_REQ_MSECS | 0 (off) | Logs requests slower than this many milliseconds |
Practical changes for a shared server:
- Lower
LSAPI_MAX_PROCESS_TIMEfrom one hour to a few minutes if no customer legitimately runs long web requests. Long jobs belong in cron, not behind a browser request. - Turn on
LSAPI_SLOW_REQ_MSECS(for example 10000) for a week to see which scripts are slow. - Keep PHP’s own
max_execution_timereasonable; it limits PHP execution, although time spent waiting on some external calls may not count towards it. - Replace WordPress’s page-load cron with a real cron job for busy sites.
- If CSF or LFD is installed, make sure its process tracking does not kill LSPHP: LiteSpeed suggests ignoring
/usr/local/lsws/fcgi-bin/lsphp.*in the process-ignore list. - On CloudLinux, check LVE faults for the user; an entry-process or memory limit can look like stuck PHP.
Set these in the WebAdmin console under the LSPHP external application’s environment, then apply a graceful restart.
Check that it worked
ps -C lsphp -o pid,user,etime,stat,args --sort=-etime | head
grep -c "Reached max children" /usr/local/lsws/logs/error.log
- No child process older than your
LSAPI_MAX_PROCESS_TIME. - The affected site loads without 503 errors.
- With
LSAPI_SLOW_REQ_MSECSon, the slow-request log names the script you fixed less often.
Official documentation: LiteSpeed: Controlling LSPHP · LiteSpeed: LSPHP options · LiteSpeed: LSPHP modes · LiteSpeed cPanel: 503 error
Related: LiteSpeed Enterprise Review: Best Apache Replacement? · LiteSpeed Cache WordPress cPanel: Recommended Settings · PHP-FPM Slow Log Analyzer · CloudLinux 10 cPanel: CageFS and LVE Limits, Upgrade Notes · MariaDB Slow Queries on 11/12: Diagnosis Steps
See also: LiteSpeed vs OpenLiteSpeed for Hosting Servers: Which to Pick · Install OpenLiteSpeed and WordPress on AlmaLinux 10 (No Panel) · PHP-FPM Calculator: pm.max_children and Spare Servers
See also: LiteSpeed 503 Service Unavailable on cPanel: Fix lsphp Limits
Frequently asked questions
Why do lsphp processes survive a LiteSpeed restart?
In detached mode PHP processes run independently of LiteSpeed. Use the .lsphp_restart.txt files or Restart Detached PHP Processes to restart them.
How do I restart PHP for one cPanel user on LiteSpeed?
Create .lsphp_restart.txt in the user’s home directory. LiteSpeed restarts only that user’s detached PHP processes.
Is killall lsphp safe?
It works, but it ends every PHP request on the server at once. Use it only when the server is unusable.
What is the default LSAPI_MAX_PROCESS_TIME?
3600 seconds. A child that spends longer than that on one request is terminated.
Why can I not kill an lsphp process in state D?
It is waiting on disk or network storage I/O. It will exit when the I/O completes; fix the storage problem.