mirror of
https://github.com/mudler/LocalAI.git
synced 2026-09-25 07:34:58 -04:00
fix(cli): ignore a half-populated socket activation environment (#11394)
A container engine started from a socket-activated system unit leaks a bare
LISTEN_PID into every container it spawns, with no matching LISTEN_FDS. LocalAI
read that as a malformed activation attempt and refused to start:
ERROR Error running the application error=loading systemd socket
activation listeners: invalid LISTEN_FDS ""
systemd's own sd_listen_fds() treats either variable being absent as "not
activated" rather than as an error, so do the same and fall back to ordinary
--address binding. A value that is present but malformed is still rejected, so
a real activation attempt cannot silently bind the wrong socket.
Fixes #11390
Assisted-by: Claude:claude-opus-5 [golangci-lint]
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
1 parent
5ac445e1d4
commit
8052c950cf
3 files changed
+41
No files matched your search
@@ -24,6 +24,14 @@ func systemdActivatedListeners() ([]net.Listener, error) {
|
||||
}
|
||||
}()
|
||||
|
||||
// A half-populated environment is not an activation attempt. Container runtimes
|
||||
// started from a socket-activated system unit leak a bare LISTEN_PID into every
|
||||
// container they spawn, and systemd's own sd_listen_fds() treats either variable
|
||||
// being absent as "not activated" rather than as an error.
|
||||
if listenPID == "" || listenFDs == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pid, err := strconv.Atoi(listenPID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid LISTEN_PID %q: %w", listenPID, err)
|
||||
|
||||
@@ -85,6 +85,34 @@ var _ = Describe("systemdActivatedListeners", func() {
|
||||
Expect(os.Getenv("LISTEN_FDNAMES")).To(BeEmpty())
|
||||
})
|
||||
|
||||
It("binds normally when the environment leaks LISTEN_PID without LISTEN_FDS", func() {
|
||||
Expect(os.Setenv("LISTEN_PID", strconv.Itoa(os.Getpid()))).To(Succeed())
|
||||
Expect(os.Unsetenv("LISTEN_FDS")).To(Succeed())
|
||||
DeferCleanup(func() {
|
||||
_ = os.Unsetenv("LISTEN_PID")
|
||||
})
|
||||
|
||||
listeners, err := systemdActivatedListeners()
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(listeners).To(BeEmpty())
|
||||
Expect(os.Getenv("LISTEN_PID")).To(BeEmpty())
|
||||
})
|
||||
|
||||
It("binds normally when the environment leaks LISTEN_FDS without LISTEN_PID", func() {
|
||||
Expect(os.Unsetenv("LISTEN_PID")).To(Succeed())
|
||||
Expect(os.Setenv("LISTEN_FDS", "1")).To(Succeed())
|
||||
DeferCleanup(func() {
|
||||
_ = os.Unsetenv("LISTEN_FDS")
|
||||
})
|
||||
|
||||
listeners, err := systemdActivatedListeners()
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(listeners).To(BeEmpty())
|
||||
Expect(os.Getenv("LISTEN_FDS")).To(BeEmpty())
|
||||
})
|
||||
|
||||
It("reports malformed activation metadata instead of silently binding another socket", func() {
|
||||
Expect(os.Setenv("LISTEN_PID", strconv.Itoa(os.Getpid()))).To(Succeed())
|
||||
Expect(os.Setenv("LISTEN_FDS", "not-a-number")).To(Succeed())
|
||||
|
||||
@@ -111,6 +111,11 @@ For a Podman-managed container, configure Podman to preserve and pass the
|
||||
systemd socket file descriptor into the container. The LocalAI process inside
|
||||
the container consumes the same activation protocol.
|
||||
|
||||
Activation needs both `LISTEN_PID` and `LISTEN_FDS`. If only one of them is set,
|
||||
LocalAI ignores them and binds `--address` as usual. A container engine started
|
||||
from a socket-activated system unit can leak a bare `LISTEN_PID` into every
|
||||
container it spawns, and that is not an activation attempt.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Try it out with examples](/basics/try/)
|
||||
|
||||
Reference in new issue
Block a user