struct master_admin_client {
struct connection conn;
+ int refcount;
struct ioloop *wait_ioloop;
bool reply_pending;
static struct connection_list *master_admin_clients = NULL;
static struct master_admin_client_callback master_admin_client_callbacks;
+static void master_admin_client_ref(struct master_admin_client *client)
+{
+ i_assert(client->refcount > 0);
+ client->refcount++;
+}
+
+static void master_admin_client_unref(struct master_admin_client **_client)
+{
+ struct master_admin_client *client = *_client;
+
+ i_assert(client->refcount > 0);
+ *_client = NULL;
+
+ if (--client->refcount == 0)
+ i_free(client);
+}
+
static void
cmd_kick_user(struct master_admin_client *client, const char *const *args)
{
the signal. */
master_service_set_last_kick_signal_user(master_service, user);
/* Don't send a response back, just like the signal handler won't. */
+ client->reply_pending = FALSE;
+ master_admin_client_unref(&client);
}
static int
io_loop_stop(client->wait_ioloop);
}
+ /* Delay freeing the client until reply is sent */
+ master_admin_client_ref(client);
client->reply_pending = TRUE;
+
if (strcmp(cmd, "KICK-USER") == 0 &&
master_admin_client_callbacks.cmd_kick_user != NULL)
cmd_kick_user(client, args);
!master_admin_client_callbacks.cmd(client, cmd, args)) {
client->reply_pending = FALSE;
o_stream_nsend_str(conn->output, "-Unknown command\n");
+ master_admin_client_unref(&client);
}
return 1;
}
connection_input_resume(&client->conn);
} else {
/* client already disconnected */
- i_free(client);
+ master_admin_client_unref(&client);
}
}
container_of(conn, struct master_admin_client, conn);
connection_deinit(conn);
- /* if reply is pending, delay freeing the client until reply is sent */
- if (!client->reply_pending)
- i_free(client);
+ master_admin_client_unref(&client);
}
static const struct connection_settings master_admin_conn_set = {
}
client = i_new(struct master_admin_client, 1);
+ client->refcount = 1;
connection_init_server(master_admin_clients, &client->conn, master_conn->name,
master_conn->fd, master_conn->fd);
if (master_service_get_client_limit(master_service) == 1) {
blocking the SIGTERM, so try for a while to read the command
here. This way the command can be handled more reliably
instead of SIGTERM interrupting its handling too early. */
+ master_admin_client_ref(client);
master_admin_client_initial_read(client);
+ master_admin_client_unref(&client);
}
}