Skip to content

Send piler's syslog output to stderr - #33

Closed
stephdl wants to merge 2 commits into
drain-on-stopfrom
piler-logs-to-stderr
Closed

stephdl wants to merge 2 commits into
drain-on-stopfrom
piler-logs-to-stderr

Conversation

@stephdl

@stephdl stephdl commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #31, itself stacked on #30. Retarget as those merge.

Problem

piler and piler-smtp log exclusively through syslog(3). There is no syslog daemon in this image and no /dev/log socket — /dev is a root-owned tmpfs created by the runtime, and the container is uid 1000 with cap_drop: ALL, so nothing can create one. Every line the two daemons produced was silently discarded. They were the only things in the container without logs, while nginx and php-fpm stream to stdout/stderr.

This is not theoretical: diagnosing a failure during #30 required injecting a syslog collector with podman exec --user root to see anything at all.

Change

config/syslog-to-stderr.c is a ~40-line LD_PRELOAD shim that overrides openlog, syslog, vsyslog, __syslog_chk and __vsyslog_chk and writes ident[pid]: message to stderr, expanding %m the way glibc does. __syslog_chk is the one that matters — the released binaries are built fortified:

$ nm -D --undefined-only /usr/sbin/piler | grep -i syslog
                 U __syslog_chk@GLIBC_2.4

It is compiled in its own build stage (gcc and libc6-dev never reach the runtime image) and preloaded for piler, piler-smtp and supercronic only — not for php-fpm or nginx, which have real log configuration.

Upstream is the better place to fix this: LOG_PERROR when not daemonising, or a config toggle. Since #30 both daemons run in the foreground, so that flag alone would do it. The shim can be dropped if that lands.

Validation

Built and run through the full compose stack. Before this change podman logs piler had no piler lines at all; now:

piler-smtp[62]: piler-smtp 1.4.9-d3f4b07 starting
piler[96]: piler 1.4.9-d3f4b07 starting
piler-smtp[62]: received: HGSCNS7IQOF4EMLY, from=s@example.com, size=95, client=10.89.0.5, fd=5, fsync=4121
piler[97]: 0/HGSCNS7IQOF4EMLY: 5000...fd61, size=95/112, attachments=0, message-id=<shim-1@example.com>, status=stored
piler-smtp[62]: piler-smtp has been terminated
piler[96]: piler has been terminated

Also re-ran #31's drain scenario under the shim: 200 mails sent, stop -t 60 logged draining spool, 34 file(s) left then spool drained, and all 200 were archived. Compiles clean with -Wall -Wextra.

piler and piler-smtp only log through syslog(3), and a rootless container
has no /dev/log to receive it, so their logs were dropped entirely. An
LD_PRELOAD shim rewrites those calls to stderr, which supervisord ships
to the container log like nginx's and php-fpm's. The binaries are built
fortified, so __syslog_chk is the symbol that matters.
Also add validate.yml to build.yml's path filters: a CI-only change did not
trigger build, so validate never ran on it.
@stephdl
stephdl deleted the branch drain-on-stop August 25, 2026 13:34
@stephdl stephdl closed this Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant