If you manage a Linux server running cPanel and ConfigServer Security & Firewall (CSF), you have likely encountered the frustrating moment when the Login Failure Daemon (LFD) refuses to start and systemd reports an alarming error: status=9/KILL.
Seeing a daemon exit with signal 9 immediately after running start can be unnerving. A SIGKILL generally means that the kernel or an external process terminated execution without allowing any cleanup. To make matters worse, running firewall validation tools directly often leads to misleading errors about missing Perl modules.
I recently resolved this exact problem on an AlmaLinux host running cPanel. Below is what actually triggers signal 9, why the Perl error was an innocent distraction, and how to get LFD running properly in a few commands.
The symptom and the status 9/kill error#
Checking the service state through systemd immediately after the failure:
systemctl status lfd.service
The output displayed:
● lfd.service - ConfigServer Firewall & Security - lfd
Loaded: loaded (/usr/lib/systemd/system/lfd.service; enabled; vendor preset: disabled)
Active: failed (Result: signal) since Mon 2026-09-14 02:20:11 -03; 4s ago
Process: 14820 ExecStart=/usr/sbin/lfd (code=killed, signal=KILL)
Main PID: 14820 (code=killed, signal=KILL)
Status: "Starting lfd..."
Unlike SIGTERM (signal 15), which gently requests that a process close open handles and exit cleanly, SIGKILL (signal 9) is immediate:
- The kernel scheduler drops the process from the execution queue right away.
- Allocated memory pages are instantly released.
- No exit hooks or cleanup routines (like deleting
.pidfiles) can run.
When a background daemon crashes this abruptly during boot, the usual suspects are memory exhaustion via the OOM Killer or a deliberate fail-safe exit triggered by the firewall wrapper script.
The misleading cpstrict.pm perl error#
Attempting to diagnose the failure, the first instinct was running CSF's functional test script:
perl /usr/local/csf/bin/csftest.pl
The terminal returned:
Can't locate cPstrict.pm in @INC (you may need to install the cPstrict module) (@INC contains: /usr/local/cpanel /usr/local/lib64/perl5 ...) at /usr/local/csf/bin/csftest.pl line 14.
BEGIN failed--compilation aborted at /usr/local/csf/bin/csftest.pl line 14.
In Perl, the @INC array stores directory paths where the interpreter searches for modules (.pm). On cPanel systems, internal modules like cPstrict.pm live inside dedicated paths under /usr/local/cpanel/.
Invoking the script directly using /usr/bin/perl without the full cPanel environment caused Perl to complain about the missing library. While this looked like broken dependencies, it was simply an artifact of how the command was executed manually. The daemon failure had nothing to do with damaged Perl packages.
The root cause: the TESTING mode safety brake#
The answer was neither in systemd status outputs nor in Perl compilation errors. It was clearly recorded inside the application log:
cat /var/log/lfd.log | tail -n 20
The log revealed:
*Error* lfd will not run with TESTING enabled in /etc/csf/csf.conf, at line 112
daemon stopped
By default, CSF installs with TESTING = "1". This testing mode is an intentional safeguard: it applies firewall rules, but schedules a temporary cron job that flushes iptables every few minutes to prevent you from being locked out of your server due to a typo in port configurations.
LFD, however, is the active monitoring engine that scans auth logs and bans malicious IPs. While testing mode is enabled, LFD calls Perl's die() function upon loading its configuration. The CSF execution wrapper halts, and systemd logs the abrupt termination with a signal status.
Other scenarios worth checking in SIGKILL events#
Before assuming testing mode is always the culprit, two edge cases produce identical symptoms and are worth a quick check:
1. Out of memory (OOM killer)#
If the server suffers from severe memory exhaustion and LFD attempts to load massive blocklists (such as a csf.deny with hundreds of thousands of entries), the kernel might select the Perl process for termination.
To verify:
dmesg -T | grep -i "out of memory"
grep -i "killed process" /var/log/messages
If no OOM events match the timestamp, memory was not the cause.
2. systemd startup timeout (timeoutstartsec)#
If disk I/O wait is heavily saturated, initial parsing of large log files might exceed systemd's default 90-second timeout. When that happens, systemd issues a forced kill.
To verify:
journalctl -u lfd.service --since "10 minutes ago" | grep -i "timeout"
Step-by-step resolution workflow#
Once confirmed that testing mode caused the shutdown, fixing it takes four commands:
1. Disable TESTING mode in configuration#
Use sed to make an immediate, in-place edit:
sed -i 's/^TESTING = "1"/TESTING = "0"/' /etc/csf/csf.conf
2. Confirm the parameter was updated#
Verify that the directive reflects zero:
grep "^TESTING =" /etc/csf/csf.conf
# Expected output: TESTING = "0"
3. Reload CSF and restart LFD together#
Rather than restarting only through systemctl, use CSF's native restart flag -r. It flushes iptables rules, reloads configuration tables, and restarts the daemon synchronously:
csf -r
4. Check service status#
Confirm that LFD is running normally:
systemctl status lfd.service
Best practices for monitoring LFD without noise#
Once the service is active, monitor log activity during the first few minutes to confirm that security checks are functioning:
# Monitor the log while filtering internal process polling noise
tail -f /var/log/lfd.log | grep -v "P_WATCH"
The key takeaway here is knowing where to look. Generic systemd kill signals (status=9/KILL) only indicate that a process was stopped, but rarely explain why. Checking the application log (/var/log/lfd.log) directly saves you from chasing false leads in system libraries.
Was this article helpful?
Leave a quick reaction to help prioritize future technical guides:
This post is licensed under CC BY-NC.



Comments
Join the discussion below.
0 comments