]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap, pop3: Close auth/config connections when we stop accepting more connections.
authorTimo Sirainen <tss@iki.fi>
Mon, 14 Dec 2009 02:08:41 +0000 (21:08 -0500)
committerTimo Sirainen <tss@iki.fi>
Mon, 14 Dec 2009 02:08:41 +0000 (21:08 -0500)
--HG--
branch : HEAD

src/lib-master/master-login-auth.c
src/lib-master/master-login-auth.h
src/lib-master/master-login.c
src/lib-master/master-login.h
src/lib-master/master-service-private.h
src/lib-master/master-service.c

index 8d15a9f9ec3117e63cd1aa0bdbe030b2bea4f735..c6cf7c05529ae5d90d885c526029e4764e1058c4 100644 (file)
@@ -51,7 +51,7 @@ struct master_login_auth *master_login_auth_init(const char *auth_socket_path)
        return auth;
 }
 
-static void master_login_auth_disconnect(struct master_login_auth *auth)
+void master_login_auth_disconnect(struct master_login_auth *auth)
 {
        struct hash_iterate_context *iter;
        void *key, *value;
index 7dd485ae0a26e3b5ff34659207444b2766234218..785e73f589690cf31735598eeac50d5d8281f55a 100644 (file)
@@ -9,6 +9,7 @@ master_login_auth_request_callback_t(const char *const *auth_args,
 
 struct master_login_auth *master_login_auth_init(const char *auth_socket_path);
 void master_login_auth_deinit(struct master_login_auth **auth);
+void master_login_auth_disconnect(struct master_login_auth *auth);
 
 void master_login_auth_request(struct master_login_auth *auth,
                               const struct master_auth_request *req,
index 87bdff6bf4a140dba32302e8c0a5aa039e3a34a4..d145ad3d388833e09b5b2a88de62ce35c3c9586a 100644 (file)
@@ -41,6 +41,8 @@ struct master_login {
        struct master_login_connection *conns;
        struct master_login_auth *auth;
        char *postlogin_socket_path;
+
+       unsigned int stopping:1;
 };
 
 static void master_login_conn_deinit(struct master_login_connection **_conn);
@@ -57,7 +59,9 @@ master_login_init(struct master_service *service, const char *auth_socket_path,
        login->callback = callback;
        login->auth = master_login_auth_init(auth_socket_path);
        login->postlogin_socket_path = i_strdup(postlogin_socket_path);
-       service->login_connections = TRUE;
+
+       i_assert(service->login == NULL);
+       service->login = login;
        return login;
 }
 
@@ -67,6 +71,9 @@ void master_login_deinit(struct master_login **_login)
 
        *_login = NULL;
 
+       i_assert(login->service->login == login);
+       login->service->login = NULL;
+
        master_login_auth_deinit(&login->auth);
        while (login->conns != NULL) {
                struct master_login_connection *conn = login->conns;
@@ -147,19 +154,26 @@ static void master_login_auth_finish(struct master_login_client *client,
                                     const char *const *auth_args)
 {
        struct master_login_connection *conn = client->conn;
-       struct master_service *service = conn->login->service;
-       bool close_config;
+       struct master_login *login = conn->login;
+       struct master_service *service = login->service;
+       bool close_sockets;
 
-       close_config = service->master_status.available_count == 0 &&
+       close_sockets = service->master_status.available_count == 0 &&
                service->service_count_left == 1;
 
-       conn->login->callback(client, auth_args[0], auth_args+1);
+       login->callback(client, auth_args[0], auth_args+1);
        i_free(client);
 
-       if (close_config) {
+       if (close_sockets) {
                /* we're dying as soon as this connection closes. */
+               i_assert(master_login_auth_request_count(login->auth) == 0);
+               master_login_auth_disconnect(login->auth);
+
                master_service_close_config_fd(service);
                master_login_conn_deinit(&conn);
+       } else if (login->stopping) {
+               /* try stopping again */
+               master_login_stop(login);
        }
 }
 
@@ -393,3 +407,12 @@ static void master_login_conn_deinit(struct master_login_connection **_conn)
        master_service_io_listeners_add(conn->login->service);
        i_free(conn);
 }
+
+void master_login_stop(struct master_login *login)
+{
+       login->stopping = TRUE;
+       if (master_login_auth_request_count(login->auth) == 0) {
+               master_login_auth_disconnect(login->auth);
+               master_service_close_config_fd(login->service);
+       }
+}
index 4b4468226392970f4bd79d1dce305207665adb4b..6603dfc046d84d8e7aacdf94af46b93768ef12c0 100644 (file)
@@ -22,5 +22,6 @@ master_login_init(struct master_service *service, const char *auth_socket_path,
 void master_login_deinit(struct master_login **login);
 
 void master_login_add(struct master_login *login, int fd);
+void master_login_stop(struct master_login *login);
 
 #endif
index 9208b8748fd10501d1579d449a0003918a69d77b..b09b67ed8d43bcb7fcb75ae396d73f737de57509 100644 (file)
@@ -41,6 +41,8 @@ struct master_service {
        void (*avail_overflow_callback)(void);
        struct timeout *to_overflow_state;
 
+       struct master_login *login;
+
        master_service_connection_callback_t *callback;
 
        pool_t set_pool;
@@ -54,9 +56,6 @@ struct master_service {
        unsigned int die_with_master:1;
        unsigned int call_avail_overflow:1;
        unsigned int delay_status_updates:1;
-       /* incoming connections are going to master-login and they're not
-          counted as real connections */
-       unsigned int login_connections:1;
 };
 
 void master_service_io_listeners_add(struct master_service *service);
index a8c061ed15e1eb2a9cee38928ee6e3f18a01ed01..db428c18b1897fbbef0f97b09e82545027e46481 100644 (file)
@@ -11,6 +11,7 @@
 #include "fd-close-on-exec.h"
 #include "settings-parser.h"
 #include "syslog-util.h"
+#include "master-login.h"
 #include "master-service-private.h"
 #include "master-service-settings.h"
 
@@ -503,6 +504,8 @@ void master_service_stop_new_connections(struct master_service *service)
                service->master_status.available_count = 0;
                master_status_update(service);
        }
+       if (service->login != NULL)
+               master_login_stop(service->login);
 }
 
 void master_service_anvil_send(struct master_service *service, const char *cmd)
@@ -693,7 +696,10 @@ static void master_service_listen(struct master_service_listener *l)
        conn.ssl = l->ssl;
        net_set_nonblock(conn.fd, TRUE);
 
-       if (!service->login_connections) {
+       if (service->login != NULL) {
+               /* incoming connections are going to master-login and they're
+                  not counted as real connections */
+       } else {
                i_assert(service->master_status.available_count > 0);
                service->master_status.available_count--;
                master_status_update(service);