This change also fixes many such leaks.
--HG--
branch : HEAD
struct penalty *penalty;
static struct io *log_fdpass_io;
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
bool master = conn->listen_fd == MASTER_LISTEN_FD_FIRST;
+ master_service_client_connection_accept(conn);
anvil_connection_create(conn->fd, master, conn->fifo);
}
pool_unref(&auth_set_pool);
}
-static void worker_connected(const struct master_service_connection *conn)
+static void worker_connected(struct master_service_connection *conn)
{
if (auth_worker_client != NULL) {
i_error("Auth workers can handle only a single client");
- (void)close(conn->fd);
return;
}
+ master_service_client_connection_accept(conn);
(void)auth_worker_client_create(auth_find_service(NULL), conn->fd);
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
enum auth_socket_type *type;
const char *path, *name, *suffix;
default:
i_unreached();
}
+ master_service_client_connection_accept(conn);
}
#include "config-parser.h"
#include "config-request.h"
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
+ master_service_client_connection_accept(conn);
config_connection_create(conn->fd);
}
/* hope that other processes relying on us will die first. */
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
+ master_service_client_connection_accept(conn);
dict_connection_create(conn->fd);
}
return 0;
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
struct auth_connection *auth;
const char *path, *name;
if (conn->fifo) {
if (notify_conn != NULL) {
i_error("Received another proxy-notify connection");
- (void)close(conn->fd);
return;
}
+ master_service_client_connection_accept(conn);
notify_conn = notify_connection_init(director, conn->fd);
return;
}
if (net_getpeername(conn->fd, &ip, &port) == 0 &&
(IPADDR_IS_V4(&ip) || IPADDR_IS_V6(&ip))) {
/* TCP/IP connection - this is another director */
- if (director_client_connected(conn->fd, &ip) < 0)
- (void)close(conn->fd);
+ if (director_client_connected(conn->fd, &ip) == 0)
+ master_service_client_connection_accept(conn);
return;
}
len = strlen(name);
if (len > 6 && strcmp(name + len - 6, "-admin") == 0) {
/* doveadm connection */
+ master_service_client_connection_accept(conn);
(void)doveadm_connection_init(director, conn->fd);
} else {
/* login connection */
auth = auth_connection_init(auth_socket_path);
- if (auth_connection_connect(auth) == 0)
+ if (auth_connection_connect(auth) == 0) {
+ master_service_client_connection_accept(conn);
login_connection_init(director, conn->fd, auth);
- else {
- (void)close(conn->fd);
+ } else {
auth_connection_deinit(&auth);
}
}
master_service_client_connection_destroyed(master_service);
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
if (dns_client != NULL) {
i_error("dns-client must be configured with client_limit=1");
- (void)close(conn->fd);
return;
}
+
+ master_service_client_connection_accept(conn);
dns_client = dns_client_create(conn->fd);
}
}
static void
-dsync_connected(const struct master_service_connection *conn ATTR_UNUSED)
+dsync_connected(struct master_service_connection *conn ATTR_UNUSED)
{
i_fatal("Running as service not supported currently");
}
}
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
if (master_login == NULL) {
/* running standalone, we shouldn't even get here */
- (void)close(conn->fd);
} else {
+ master_service_client_connection_accept(conn);
master_login_add(master_login, conn->fd);
}
}
}
}
+void master_service_client_connection_accept(struct master_service_connection *conn)
+{
+ conn->accepted = TRUE;
+}
+
void master_service_client_connection_destroyed(struct master_service *service)
{
/* we can listen again */
master_status_update(service);
service->callback(&conn);
+
+ if (!conn.accepted) {
+ if (close(conn.fd) < 0)
+ i_error("close(service connection) failed: %m");
+ master_service_client_connection_destroyed(service);
+ }
}
static void io_listeners_init(struct master_service *service)
unsigned int fifo:1;
unsigned int ssl:1;
+
+ unsigned int accepted:1;
};
typedef void
-master_service_connection_callback_t(const struct master_service_connection *conn);
+master_service_connection_callback_t(struct master_service_connection *conn);
extern struct master_service *master_service;
/* Send command to anvil process, if we have fd to it. */
void master_service_anvil_send(struct master_service *service, const char *cmd);
+/* Call to accept the client connection. Otherwise the connection is closed. */
+void master_service_client_connection_accept(struct master_service_connection *conn);
/* Call whenever a client connection is destroyed. */
void master_service_client_connection_destroyed(struct master_service *service);
const char *dns_client_socket_path;
struct mail_storage_service_ctx *storage_service;
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
+ master_service_client_connection_accept(conn);
(void)client_create(conn->fd, conn->fd, conn);
}
log_connections_deinit();
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
+ master_service_client_connection_accept(conn);
log_connection_create(conn->fd, conn->listen_fd);
}
}
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
const char *access_sockets =
global_login_settings->login_access_sockets;
struct login_access_lookup *lookup;
+ master_service_client_connection_accept(conn);
+
/* make sure we're connected (or attempting to connect) to auth */
auth_client_connect(auth_client);
}
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
if (master_login == NULL) {
/* running standalone, we shouldn't even get here */
- (void)close(conn->fd);
} else {
+ master_service_client_connection_accept(conn);
master_login_add(master_login, conn->fd);
}
}
}
}
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
+ master_service_client_connection_accept(conn);
if (ssl_params->used == 0) {
/* waiting for parameter building to finish */
if (!array_is_created(&delayed_fds))
static const char **exec_args;
static bool drop_privileges = FALSE;
-static void client_connected(const struct master_service_connection *conn)
+static void client_connected(struct master_service_connection *conn)
{
enum mail_storage_service_flags flags =
MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS;
i_fatal("read() failed: %m");
else
i_fatal("read() failed: disconnected");
- (void)close(conn->fd);
- return;
}
if (fd == -1)
i_fatal("client fd not received");
{
if (tcpwrap_client != NULL) {
i_error("tcpwrap must be configured with client_limit=1");
- (void)close(conn->fd);
return;
}
+
+ master_service_client_connection_accept(conn);
tcpwrap_client = tcpwrap_client_create(conn->fd);
}