[Mimedefang] REVISED: postfix/mimedefang socket

Richard Laager rlaager at wiktel.com
Sat Dec 9 18:45:18 EST 2017


I ran into a problem with my systemd units for MIMEDefang. There is a
race condition between mimedefang-multiplexor creating the socket and
mimedefang trying to access it. If the multiplexor doesn't create the
socket in time, mimedefang fails on startup.

This is happening because Type=simple services are assumed to be running
immediately. This is documented in systemd.service(5), which says, "In
this mode, if the process offers functionality to other processes on the
system, its communication channels should be installed before the daemon
is started up (e.g. sockets set up by systemd, via socket activation),
as systemd will immediately proceed starting follow-up units."

I have attached updated versions to correct this. These change to
Type=forking and drop the -D flag. With the change to Type=forking, I
have also brought back pid files. Since systemd requires the pid file
path to be hardcoded (as the argument to PIDFile), I put it in /run
rather than the $SPOOLDIR (which the administrator can change). It can't
be directly in /run, as the daemon writes the pidfile after dropping
privileges, so we have to create a /run/mimedefang subdirectory owned by
$MX_USER. This requires some indirection, as $MX_USER can also be
customized by the administrator. I only create this directory for
mimedefang-multiplexor.service (and not mimedefang.service), as
mimedefang.service is already ordered after mimedefang-multiplexor.service.

Long term, the ideal answer is to use systemd's socket activation. This
would allow the services to startup in parallel. Another alternative
would be to use Type=notify. Either requires changes to the mimedefang C
code.

-- 
Richard
-------------- next part --------------
[Unit]
Description=MIMEDefang E-mail Filter
Documentation=man:mimedefang(8)
Before=multi-user.target
Before=postfix.service
Before=sendmail.service
After=remote-fs.target
After=systemd-journald-dev-log.socket
BindsTo=mimedefang-multiplexor.service
After=mimedefang-multiplexor.service
PropagatesReloadTo=mimedefang-multiplexor.service

[Service]
Type=forking
PIDFile=/run/mimedefang/mimedefang.pid
Restart=on-failure
TimeoutStopSec=30s
# LC_ALL=C may not be necessary for mimedefang, but it is for
# mimedefang-multiplexor, so upstream prefers it here also to be consistent.
Environment=LC_ALL=C MX_SOCKET=/var/spool/MIMEDefang/mimedefang-multiplexor.sock MX_USER=defang SOCKET=/var/spool/MIMEDefang/mimedefang.sock
EnvironmentFile=-/etc/default/mimedefang
ExecStartPre=/bin/rm -f $SOCKET
ExecStart=/bin/sh -c 'exec /usr/bin/mimedefang \
    `[ -n "$LOOPBACK_RESERVED_CONNECTIONS" ] && echo "-R $LOOPBACK_RESERVED_CONNECTIONS"` \
    -m $MX_SOCKET \
    `[ -n "$SPOOLDIR" ] && echo "-z $SPOOLDIR"` \
    `[ -n "$MX_USER" ] && echo "-U $MX_USER"` \
    `[ -n "$SYSLOG_FACILITY" ] && echo "-S $SYSLOG_FACILITY"` \
    `[ "$MX_RELAY_CHECK" = "yes" ] && echo "-r"` \
    `[ "$MX_HELO_CHECK" = "yes" ] && echo "-H"` \
    `[ "$MX_SENDER_CHECK" = "yes" ] && echo "-s"` \
    `[ "$MX_RECIPIENT_CHECK" = "yes" ] && echo "-t"` \
    `[ "$KEEP_FAILED_DIRECTORIES" = "yes" ] && echo "-k"` \
    `[ "$MD_EXTRA" != "" ] && echo $MD_EXTRA` \
    `[ "$MD_SKIP_BAD_RCPTS" = "yes" ] && echo "-N"` \
    "`[ -n "$X_SCANNED_BY" ] && \
      ( [ "$X_SCANNED_BY" = "-" ] && \
        echo "-X" || echo "-x$X_SCANNED_BY" )`" \
    `[ "$MD_ALLOW_GROUP_ACCESS" = "yes" ] && echo "-G"` \
    `[ "$ALLOW_NEW_CONNECTIONS_TO_QUEUE" = "yes" ] && echo "-q"` \
    -p $SOCKET -P /run/mimedefang/mimedefang.pid'
ExecStopPost=/bin/rm -f $SOCKET
# Make this service eligible for a reload, so we can propagate it to
# mimedefang-multiplexor.service.
ExecReload=/bin/true

[Install]
WantedBy=multi-user.target
-------------- next part --------------
[Unit]
Description=MIMEDefang E-mail Filter (Multiplexor)
Documentation=man:mimedefang-multiplexor(8)
After=remote-fs.target
After=systemd-journald-dev-log.socket
PartOf=mimedefang.service

[Service]
Type=forking
PIDFile=/run/mimedefang/mimedefang-multiplexor.pid
Restart=on-failure
TimeoutStopSec=30s
KillMode=mixed
# Locale should be set to "C" for generating valid date headers
Environment=LC_ALL=C MX_BUSY=600 MX_LOG=yes MX_MAXIMUM=10 MX_MINIMUM=2 MX_SOCKET=/var/spool/MIMEDefang/mimedefang-multiplexor.sock MX_USER=defang
EnvironmentFile=-/etc/default/mimedefang
ExecStartPre=/bin/rm -f $MX_SOCKET
ExecStartPre=/bin/sh -c '/usr/bin/install -d \
    `[ -n "$MX_USER" ] && echo "-o $MX_USER"` \
    /run/mimedefang'
ExecStart=/bin/sh -c 'HOME=${SPOOLDIR:=/var/spool/MIMEDefang} \
    exec /usr/bin/mimedefang-multiplexor \
    `[ "$MX_EMBED_PERL" = "yes" ] && echo "-E"` \
    `[ -n "$SPOOLDIR" ] && echo "-z $SPOOLDIR"` \
    `[ -n "$FILTER" ] && echo "-f $FILTER"` \
    `[ -n "$SYSLOG_FACILITY" ] && echo "-S $SYSLOG_FACILITY"` \
    `[ -n "$SUBFILTER" ] && echo "-F $SUBFILTER"` \
    `[ -n "$MX_MINIMUM" ] && echo "-m $MX_MINIMUM"` \
    `[ -n "$MX_MAXIMUM" ] && echo "-x $MX_MAXIMUM"` \
    `[ -n "$MX_MAP_SOCKET" ] && echo "-N $MX_MAP_SOCKET"` \
    `[ -n "$MX_LOG_SLAVE_STATUS_INTERVAL" ] && echo "-L $MX_LOG_SLAVE_STATUS_INTERVAL"` \
    `[ -n "$MX_USER" ] && echo "-U $MX_USER"` \
    `[ -n "$MX_IDLE" ] && echo "-i $MX_IDLE"` \
    `[ -n "$MX_BUSY" ] && echo "-b $MX_BUSY"` \
    `[ -n "$MX_REQUESTS" ] && echo "-r $MX_REQUESTS"` \
    `[ -n "$MX_SLAVE_DELAY" ] && echo "-w $MX_SLAVE_DELAY"` \
    `[ -n "$MX_MIN_SLAVE_DELAY" ] && echo "-W $MX_MIN_SLAVE_DELAY"` \
    `[ -n "$MX_MAX_RSS" ] && echo "-R $MX_MAX_RSS"` \
    `[ -n "$MX_MAX_AS" ] && echo "-M $MX_MAX_AS"` \
    `[ "$MX_LOG" = "yes" ] && echo "-l"` \
    `[ "$MX_STATS" = "yes" ] && echo "-t /var/log/mimedefang/stats"` \
    `[ "$MX_STATS" = "yes" -a "$MX_FLUSH_STATS" = "yes" ] && echo "-u"` \
    `[ "$MX_STATS_SYSLOG" = "yes" ] && echo "-T"` \
    `[ "$MD_ALLOW_GROUP_ACCESS" = "yes" ] && echo "-G"` \
    `[ "$MX_STATUS_UPDATES" = "yes" ] && echo "-Z"` \
    `[ -n "$MX_QUEUE_SIZE" ] && echo "-q $MX_QUEUE_SIZE"` \
    `[ -n "$MX_QUEUE_TIMEOUT" ] && echo "-Q $MX_QUEUE_TIMEOUT"` \
    `[ -n "$MX_NOTIFIER" ] && echo "-O $MX_NOTIFIER"` \
    `[ -n "$MX_RECIPOK_PERDOMAIN_LIMIT" ] && echo "-y $MX_RECIPOK_PERDOMAIN_LIMIT"` \
    -s $MX_SOCKET -p /run/mimedefang/mimedefang-multiplexor.pid'
ExecStopPost=/bin/rm -f $MX_SOCKET
ExecReload=/bin/kill -INT $MAINPID


More information about the MIMEDefang mailing list