From: Timo Sirainen Date: Mon, 14 Dec 2009 02:08:41 +0000 (-0500) Subject: imap, pop3: Close auth/config connections when we stop accepting more connections. X-Git-Tag: 2.0.beta1~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7891c8e6debdcfec552cb1beea2a0230fe89957b;p=thirdparty%2Fdovecot%2Fcore.git imap, pop3: Close auth/config connections when we stop accepting more connections. --HG-- branch : HEAD --- diff --git a/src/lib-master/master-login-auth.c b/src/lib-master/master-login-auth.c index 8d15a9f9ec..c6cf7c0552 100644 --- a/src/lib-master/master-login-auth.c +++ b/src/lib-master/master-login-auth.c @@ -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; diff --git a/src/lib-master/master-login-auth.h b/src/lib-master/master-login-auth.h index 7dd485ae0a..785e73f589 100644 --- a/src/lib-master/master-login-auth.h +++ b/src/lib-master/master-login-auth.h @@ -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, diff --git a/src/lib-master/master-login.c b/src/lib-master/master-login.c index 87bdff6bf4..d145ad3d38 100644 --- a/src/lib-master/master-login.c +++ b/src/lib-master/master-login.c @@ -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); + } +} diff --git a/src/lib-master/master-login.h b/src/lib-master/master-login.h index 4b44682263..6603dfc046 100644 --- a/src/lib-master/master-login.h +++ b/src/lib-master/master-login.h @@ -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 diff --git a/src/lib-master/master-service-private.h b/src/lib-master/master-service-private.h index 9208b8748f..b09b67ed8d 100644 --- a/src/lib-master/master-service-private.h +++ b/src/lib-master/master-service-private.h @@ -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); diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index a8c061ed15..db428c18b1 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -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);