[Dovecot] add basic systemd support to dovecot
Christophe Fergeau
cfergeau at gmail.com
Sun Nov 14 23:44:21 EET 2010
Hi,
Sorry for the delay in replying, I was away for a few weeks :) I have finally
reworked the patch according to your feedback.
On Mon, Oct 25, 2010 at 05:47:20PM +0100, Timo Sirainen wrote:
> You can simplify the environment preserving with these changes:
>
> http://hg.dovecot.org/dovecot-2.0/rev/e0a97842182f
> http://hg.dovecot.org/dovecot-2.0/rev/d1fd5b84d410
Ah, that indeed makes things much simpler, thanks!
>
> I don't think this is portable. You could do it instead like:
Ok, I changed it even after reading your other email.
>
> > + AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
> > + [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
>
> Is this a common name for this option? If not, I'd prefer a shorter
> name.
I asked upstream about it, and I was told it's the usual way of naming options
with the autotools, so they'd prefer if it was kept this way. But I don't mind
changing it to something else if you prefer, I have a patch changing it to
--with-systemd if needed.
Here is the updated patch, if you want I also have it as a patch series:
systemd: Add proper systemd configure.in blob (from daemon(7))
systemd: Preserve LISTEN_FDS and LISTEN_PID during env cleanup when systemd is used
systemd: Use sockets provided by systemd if possible
systemd: When systemd didn't provide a suitable socket, fallback to the regular socket creation code
systemd: Add systemd unit files
Christophe
-------------- next part --------------
diff --git a/Makefile.am b/Makefile.am
index d037258..8a6000a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,17 @@ dovecot-config: dovecot-config.in Makefile
-e "s|^\(dovecot_moduledir\)=|\1=$(moduledir)|" \
> dovecot-config
+if HAVE_SYSTEMD
+%.service: %.service.in
+ $(AM_V_GEN)sed -e 's, at sbindir\@,$(sbindir),g' $< > $@
+
+systemdsystemunit_DATA = \
+ dovecot.socket \
+ dovecot.service
+else
+EXTRA_DIST+= dovecot.socket dovecot.service.in
+endif
+
install-exec-hook:
rm $(DESTDIR)$(pkglibdir)/dovecot-config && \
grep -v '^LIBDOVECOT_.*_INCLUDE' dovecot-config | \
@@ -62,6 +73,9 @@ install-exec-hook:
> $(DESTDIR)$(pkglibdir)/dovecot-config
CLEANFILES = $(datafiles)
+if HAVE_SYSTEMD
+CLEANFILES += $systedmsystemunit_DATA
+endif
DISTCLEANFILES = $(top_builddir)/dovecot-version.h
diff --git a/configure.in b/configure.in
index 348f441..ecb3046 100644
--- a/configure.in
+++ b/configure.in
@@ -2628,6 +2628,16 @@ fi
AC_SUBST(RUN_TEST)
AC_SUBST(abs_top_builddir)
+PKG_PROG_PKG_CONFIG
+AC_ARG_WITH([systemdsystemunitdir],
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+if test "x$with_systemdsystemunitdir" != xno; then
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+ AC_DEFINE(HAVE_SYSTEMD,, Define if you want to use systemd socket activation)
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
+
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
diff --git a/dovecot.service.in b/dovecot.service.in
new file mode 100644
index 0000000..db03946
--- /dev/null
+++ b/dovecot.service.in
@@ -0,0 +1,8 @@
+[Unit]
+Description=Dovecot IMAP/POP3 email server
+After=local-fs.target network.target
+
+[Service]
+Type=simple
+ExecStart=@sbindir@/dovecot -F
+NonBlocking=yes
diff --git a/dovecot.socket b/dovecot.socket
new file mode 100644
index 0000000..0fdef6f
--- /dev/null
+++ b/dovecot.socket
@@ -0,0 +1,15 @@
+[Unit]
+Description=Dovecot IMAP/POP3 email server activation socket
+
+[Socket]
+#dovecot expects separate IPv4 and IPv6 sockets
+BindIPv6Only=ipv6-only
+ListenStream=0.0.0.0:143
+ListenStream=[::]:143
+ListenStream=0.0.0.0:993
+ListenStream=[::]:993
+KeepAlive=true
+
+[Install]
+WantedBy=sockets.target
+
diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c
index e2dc98d..5925bb6 100644
--- a/src/lib-master/master-service.c
+++ b/src/lib-master/master-service.c
@@ -400,6 +400,10 @@ void master_service_env_clean(bool preserve_home)
#ifdef DEBUG
"GDB",
#endif
+#ifdef HAVE_SYSTEMD
+ "LISTEN_PID",
+ "LISTEN_FDS",
+#endif
NULL
};
env_clean_except(preserve_envs + (preserve_home ? 0 : 1));
diff --git a/src/master/Makefile.am b/src/master/Makefile.am
index 526b75b..9d3ad78 100644
--- a/src/master/Makefile.am
+++ b/src/master/Makefile.am
@@ -2,6 +2,11 @@ pkglibexecdir = $(libexecdir)/dovecot
sbin_PROGRAMS = dovecot
+if HAVE_SYSTEMD
+SYSTEMD_SOURCES = sd-daemon.c
+endif
+
+
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
@@ -27,13 +32,15 @@ dovecot_SOURCES = \
service-monitor.c \
service-process.c \
service-process-notify.c \
- service.c
+ service.c \
+ $(SYSTEMD_SOURCES)
noinst_HEADERS = \
capabilities.h \
common.h \
dup2-array.h \
master-settings.h \
+ sd-daemon.h \
service-anvil.h \
service-listen.h \
service-log.h \
@@ -41,3 +48,4 @@ noinst_HEADERS = \
service-process.h \
service-process-notify.h \
service.h
+
diff --git a/src/master/main.c b/src/master/main.c
index 5e390d6..2d862a0 100644
--- a/src/master/main.c
+++ b/src/master/main.c
@@ -601,6 +601,10 @@ int main(int argc, char *argv[])
static const char *preserve_envs[] = {
/* AIX depends on TZ to get the timezone correctly. */
"TZ",
+#ifdef HAVE_SYSTEMD
+ "LISTEN_PID",
+ "LISTEN_FDS",
+#endif
NULL
};
struct master_settings *set;
diff --git a/src/master/service-listen.c b/src/master/service-listen.c
index 318c098..976036b 100644
--- a/src/master/service-listen.c
+++ b/src/master/service-listen.c
@@ -5,6 +5,9 @@
#include "fd-set-nonblock.h"
#include "fd-close-on-exec.h"
#include "network.h"
+#ifdef HAVE_SYSTEMD
+#include "sd-daemon.h"
+#endif
#include "service.h"
#include "service-listen.h"
@@ -147,20 +150,47 @@ static int service_inet_listener_listen(struct service_listener *l)
struct service *service = l->service;
const struct inet_listener_settings *set = l->set.inetset.set;
unsigned int port = set->port;
- int fd;
-
- fd = net_listen(&l->set.inetset.ip, &port,
- service_get_backlog(service));
- if (fd < 0) {
- service_error(service, "listen(%s, %u) failed: %m",
- l->inet_address, set->port);
- return errno == EADDRINUSE ? 0 : -1;
+ int fd = -1;
+#ifdef HAVE_SYSTEMD
+ int n;
+
+ n = sd_listen_fds(0);
+ if (n < 0) {
+ errno = -n;
+ goto failure;
+ } else if (n > 0) {
+ for (fd = SD_LISTEN_FDS_START;
+ fd <= SD_LISTEN_FDS_START + n - 1;
+ fd++) {
+ if (sd_is_socket_inet(fd, l->set.inetset.ip.family,
+ SOCK_STREAM, 1, port))
+ break;
+ }
+ if (fd > SD_LISTEN_FDS_START + n - 1) {
+ /* when systemd didn't provide a usable socket,
+ * fall back to the regular socket creation code
+ */
+ fd = -1;
+ }
+ }
+#endif
+
+ if (fd == -1) {
+ fd = net_listen(&l->set.inetset.ip, &port,
+ service_get_backlog(service));
+ if (fd < 0)
+ goto failure;
+ net_set_nonblock(fd, TRUE);
+ fd_close_on_exec(fd, TRUE);
}
- net_set_nonblock(fd, TRUE);
- fd_close_on_exec(fd, TRUE);
l->fd = fd;
return 1;
+
+failure:
+ service_error(service, "listen(%s, %u) failed: %m",
+ l->inet_address, set->port);
+ return errno == EADDRINUSE ? 0 : -1;
}
static int service_listen(struct service *service)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
Url : http://dovecot.org/pipermail/dovecot/attachments/20101114/777eaa8d/attachment.bin
More information about the dovecot
mailing list