Le 18 févr. 2013 à 10:28, Axel Luttgens a écrit :

> [...]
> 
> It seems it could be easily back ported to 2.1.x.
> I'll try and report back here.

Hello Timo,

Please find hereafter a proposal based on 2.1.4.
Tested here, no hangs anymore with virtual uids/gids.

I'm just wondering about the call to hostpid_init() at line 364 of 
master/main.c, the one related to a config reload; since provisions seem to 
have been made for taking a possible hostname change into account, wouldn't it 
be needed to unset the environment variables there?

Axel


--- src/lib/hostpid.c.original  2013-02-18 12:46:25.000000000 +0100
+++ src/lib/hostpid.c   2013-02-18 17:18:32.000000000 +0100
@@ -3,9 +3,12 @@
 #include "lib.h"
 #include "hostpid.h"
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <netdb.h>
 
+#define HOSTNAME_DISALLOWED_CHARS "/\r\n\t"
+
 const char *my_hostname = NULL;
 const char *my_pid = NULL;
 
@@ -15,13 +18,19 @@
 {
        static char hostname[256], pid[MAX_INT_STRLEN];
 
-       if (gethostname(hostname, sizeof(hostname)-1) == -1)
-               i_strocpy(hostname, "unknown", sizeof(hostname));
-       hostname[sizeof(hostname)-1] = '\0';
-       my_hostname = hostname;
+       /* Children should find MY_HOSTNAME_ENV set by master process.  */
+       /* Only master process should have to call gethostname() once.  */
+       my_hostname = getenv(MY_HOSTNAME_ENV);
+       if (my_hostname == NULL) {
+               if (gethostname(hostname, sizeof(hostname)-1) < 0)
+                       i_fatal("gethostname() failed: %m");
+               hostname[sizeof(hostname)-1] = '\0';
+               my_hostname = hostname;
+       }
 
-       if (strchr(hostname, '/') != NULL)
-               i_fatal("Invalid system hostname: %s", hostname);
+       if (my_hostname[0] == '\0' ||
+                       strcspn(my_hostname, HOSTNAME_DISALLOWED_CHARS) != 
strlen(my_hostname))
+               i_error("Invalid system hostname: '%s'", my_hostname);
 
        /* allow calling hostpid_init() multiple times to reset hostname */
        i_free_and_null(my_domain);
@@ -35,12 +44,17 @@
        struct hostent *hent;
        const char *name;
 
+       /* Children should find MY_HOSTDOMAIN_ENV set by master process.        
*/
+       /* Only master process should have to call gethostbyname() once.        
*/
        if (my_domain == NULL) {
-               hent = gethostbyname(my_hostname);
-               name = hent != NULL ? hent->h_name : NULL;
+               name = getenv(MY_HOSTDOMAIN_ENV);
                if (name == NULL) {
-                       /* failed, use just the hostname */
-                       name = my_hostname;
+                       hent = gethostbyname(my_hostname);
+                       name = hent != NULL ? hent->h_name : NULL;
+                       if (name == NULL) {
+                               /* failed, use just the hostname */
+                               name = my_hostname;
+                       }
                }
                my_domain = i_strdup(name);
        }

--- src/lib/hostpid.h.original  2013-02-18 13:13:44.000000000 +0100
+++ src/lib/hostpid.h   2013-02-18 13:21:24.000000000 +0100
@@ -11,5 +11,10 @@
    hostname. */
 const char *my_hostdomain(void);
 
+/* When set, these environments override above my_hostname and static 
my_domain.       */
+/* Master process normally sets these to child processes.                      
                                */
+#define MY_HOSTNAME_ENV "DOVECOT_HOSTNAME"
+#define MY_HOSTDOMAIN_ENV "DOVECOT_HOSTDOMAIN"
+
 #endif
 
--- src/master/service-process.c.original       2013-02-18 13:24:23.000000000 
+0100
+++ src/master/service-process.c        2013-02-18 13:39:15.000000000 +0100
@@ -234,6 +234,8 @@
                                        service->set->service_count));
        }
        env_put(t_strdup_printf(MASTER_UID_ENV"=%u", uid));
+       env_put(t_strdup_printf(MY_HOSTNAME_ENV"=%s", my_hostname));
+       env_put(t_strdup_printf(MY_HOSTDOMAIN_ENV"=%s", my_hostdomain()));
 
        if (!service->set->master_set->version_ignore)
                env_put(MASTER_DOVECOT_VERSION_ENV"="PACKAGE_VERSION);


Reply via email to