nm-sudo,dispatcher: rename and refactor code to make them more similar

nm-sudo and nm-dispatcher are very similar from a high level. Both are D-Bus activated
services that exit on idle and all they do, is to provide a simple D-Bus API with no
objects or properties.

Hence it's not surprising that they follow the same structure.

Rename the code to make them look more similar.
This commit is contained in:
Thomas Haller 2021-08-04 11:53:30 +02:00
parent 412b5b4fa7
commit 2665fe23c2
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
2 changed files with 110 additions and 93 deletions

View file

@ -7,15 +7,15 @@
#include "libnm-client-aux-extern/nm-default-client.h"
#include <syslog.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <syslog.h>
#include <unistd.h>
#include "libnm-core-aux-extern/nm-dispatcher-api.h"
#include "libnm-glib-aux/nm-dbus-aux.h"
@ -33,31 +33,36 @@
typedef struct Request Request;
static struct {
typedef struct {
GDBusConnection *dbus_connection;
GCancellable * quit_cancellable;
bool log_verbose;
bool log_stdout;
gboolean persist;
GSource * quit_source;
guint request_id_counter;
guint dbus_regist_id;
bool log_verbose;
bool log_stdout;
GSource *source_idle_timeout;
gint64 start_timestamp_msec;
bool name_requested;
guint request_id_counter;
guint service_regist_id;
bool reject_new_requests;
bool exit_with_failure;
bool shutdown_timeout;
bool shutdown_quitting;
gboolean persist;
Request *current_request;
GQueue * requests_waiting;
int num_requests_pending;
} gl;
bool exit_with_failure;
bool name_requested;
bool reject_new_requests;
bool shutdown_timeout;
bool shutdown_quitting;
} GlobalData;
GlobalData gl;
typedef struct {
Request *request;
@ -206,18 +211,20 @@ request_free(Request *request)
g_slice_free(Request, request);
}
/*****************************************************************************/
static gboolean
quit_timeout_cb(gpointer user_data)
_idle_timeout_cb(gpointer user_data)
{
nm_clear_g_source_inst(&gl.quit_source);
nm_clear_g_source_inst(&gl.source_idle_timeout);
gl.shutdown_timeout = TRUE;
return G_SOURCE_CONTINUE;
}
static void
quit_timeout_reschedule(void)
_idle_timeout_restart(void)
{
nm_clear_g_source_inst(&gl.quit_source);
nm_clear_g_source_inst(&gl.source_idle_timeout);
if (gl.persist)
return;
@ -228,9 +235,11 @@ quit_timeout_reschedule(void)
if (gl.num_requests_pending > 0)
return;
gl.quit_source = nm_g_timeout_add_source(10000, quit_timeout_cb, NULL);
gl.source_idle_timeout = nm_g_timeout_add_source(10000, _idle_timeout_cb, NULL);
}
/*****************************************************************************/
/**
* next_request:
*
@ -278,7 +287,7 @@ next_request(Request *request)
* Checks if all the scripts for the request have terminated and in such case
* it sends the D-Bus response and releases the request resources.
*
* It also decreases @num_requests_pending and possibly does quit_timeout_reschedule().
* It also decreases @num_requests_pending and possibly does _idle_timeout_restart().
*/
static void
complete_request(Request *request)
@ -317,7 +326,7 @@ complete_request(Request *request)
nm_assert(gl.num_requests_pending > 0);
if (--gl.num_requests_pending <= 0) {
nm_assert(!gl.current_request && !g_queue_peek_head(gl.requests_waiting));
quit_timeout_reschedule();
_idle_timeout_restart();
}
}
@ -695,7 +704,7 @@ script_must_wait(const char *path)
}
static void
_method_call_action(GDBusMethodInvocation *invocation, GVariant *parameters)
_handle_action(GDBusMethodInvocation *invocation, GVariant *parameters)
{
const char * action;
gs_unref_variant GVariant *connection = NULL;
@ -813,7 +822,7 @@ _method_call_action(GDBusMethodInvocation *invocation, GVariant *parameters)
gl.num_requests_pending++;
gl.shutdown_timeout = FALSE;
nm_clear_g_source_inst(&gl.quit_source);
nm_clear_g_source_inst(&gl.source_idle_timeout);
for (i = 0; i < request->scripts->len; i++) {
ScriptInfo *s = g_ptr_array_index(request->scripts, i);
@ -859,7 +868,7 @@ _method_call_action(GDBusMethodInvocation *invocation, GVariant *parameters)
}
static void
_method_call_ping(GDBusMethodInvocation *invocation, GVariant *parameters)
_handle_ping(GDBusMethodInvocation *invocation, GVariant *parameters)
{
gs_free char *msg = NULL;
gint64 running_msec;
@ -879,14 +888,14 @@ _method_call_ping(GDBusMethodInvocation *invocation, GVariant *parameters)
}
static void
_method_call(GDBusConnection * connection,
const char * sender,
const char * object_path,
const char * interface_name,
const char * method_name,
GVariant * parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
_bus_method_call(GDBusConnection * connection,
const char * sender,
const char * object_path,
const char * interface_name,
const char * method_name,
GVariant * parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
if (gl.reject_new_requests) {
g_dbus_method_invocation_return_error(invocation,
@ -897,11 +906,11 @@ _method_call(GDBusConnection * connection,
}
if (nm_streq(interface_name, NM_DISPATCHER_DBUS_INTERFACE)) {
if (nm_streq(method_name, "Action")) {
_method_call_action(invocation, parameters);
_handle_action(invocation, parameters);
return;
}
if (nm_streq(method_name, "Ping")) {
_method_call_ping(invocation, parameters);
_handle_ping(invocation, parameters);
return;
}
}
@ -944,7 +953,7 @@ static gboolean
_bus_register_service(void)
{
static const GDBusInterfaceVTable interface_vtable = {
.method_call = _method_call,
.method_call = _bus_method_call,
};
gs_free_error GError * error = NULL;
NMDBusConnectionCallBlockingData data = {
@ -953,7 +962,7 @@ _bus_register_service(void)
gs_unref_variant GVariant *ret = NULL;
guint32 ret_val;
gl.dbus_regist_id =
gl.service_regist_id =
g_dbus_connection_register_object(gl.dbus_connection,
NM_DISPATCHER_DBUS_PATH,
interface_info,
@ -961,7 +970,7 @@ _bus_register_service(void)
NULL,
NULL,
&error);
if (gl.dbus_regist_id == 0) {
if (gl.service_regist_id == 0) {
_LOG_X_W("dbus: could not export dispatcher D-Bus interface %s: %s",
NM_DISPATCHER_DBUS_PATH,
error->message);
@ -1059,7 +1068,7 @@ logging_shutdown(void)
}
static gboolean
signal_handler(gpointer user_data)
_signal_callback_term(gpointer user_data)
{
if (!gl.shutdown_quitting) {
gl.shutdown_quitting = TRUE;
@ -1098,7 +1107,7 @@ _bus_release_name(void)
/* we create a fake pending request. */
gl.num_requests_pending++;
nm_clear_g_source_inst(&gl.quit_source);
nm_clear_g_source_inst(&gl.source_idle_timeout);
r = nm_sd_notify("STOPPING=1");
if (r < 0)
@ -1124,7 +1133,7 @@ _bus_release_name(void)
/*****************************************************************************/
static gboolean
parse_command_line(int *p_argc, char ***p_argv, GError **error)
_initial_setup(int *p_argc, char ***p_argv, GError **error)
{
GOptionContext *opt_ctx;
gboolean arg_debug = FALSE;
@ -1170,6 +1179,8 @@ parse_command_line(int *p_argc, char ***p_argv, GError **error)
return success;
}
/*****************************************************************************/
int
main(int argc, char **argv)
{
@ -1178,14 +1189,16 @@ main(int argc, char **argv)
GSource * source_int = NULL;
signal(SIGPIPE, SIG_IGN);
source_term = nm_g_unix_signal_add_source(SIGTERM, signal_handler, GINT_TO_POINTER(SIGTERM));
source_int = nm_g_unix_signal_add_source(SIGINT, signal_handler, GINT_TO_POINTER(SIGINT));
source_term =
nm_g_unix_signal_add_source(SIGTERM, _signal_callback_term, GINT_TO_POINTER(SIGTERM));
source_int =
nm_g_unix_signal_add_source(SIGINT, _signal_callback_term, GINT_TO_POINTER(SIGINT));
gl.start_timestamp_msec = nm_utils_clock_gettime_msec(CLOCK_BOOTTIME);
gl.quit_cancellable = g_cancellable_new();
if (!parse_command_line(&argc, &argv, &error)) {
if (!_initial_setup(&argc, &argv, &error)) {
_LOG_X_W("Error parsing command line arguments: %s", error->message);
gl.exit_with_failure = TRUE;
goto done;
@ -1219,7 +1232,7 @@ main(int argc, char **argv)
gl.requests_waiting = g_queue_new();
quit_timeout_reschedule();
_idle_timeout_restart();
if (!_bus_register_service()) {
/* we failed to start the D-Bus service, and will shut down. However,
@ -1248,19 +1261,19 @@ main(int argc, char **argv)
}
done:
nm_g_main_context_iterate_ready(NULL);
gl.shutdown_quitting = TRUE;
g_cancellable_cancel(gl.quit_cancellable);
nm_assert(gl.num_requests_pending == 0);
if (gl.dbus_regist_id != 0)
g_dbus_connection_unregister_object(gl.dbus_connection, nm_steal_int(&gl.dbus_regist_id));
if (gl.service_regist_id != 0) {
g_dbus_connection_unregister_object(gl.dbus_connection,
nm_steal_int(&gl.service_regist_id));
}
nm_clear_pointer(&gl.requests_waiting, g_queue_free);
nm_clear_g_source_inst(&gl.quit_source);
nm_clear_g_source_inst(&gl.source_idle_timeout);
if (gl.dbus_connection) {
g_dbus_connection_flush_sync(gl.dbus_connection, NULL, NULL);
@ -1276,7 +1289,6 @@ done:
nm_clear_g_source_inst(&source_term);
nm_clear_g_source_inst(&source_int);
g_clear_object(&gl.quit_cancellable);
return gl.exit_with_failure ? 1 : 0;

View file

@ -5,12 +5,12 @@
#include <gio/gunixfdlist.h>
#include "c-list/src/c-list.h"
#include "libnm-base/nm-sudo-utils.h"
#include "libnm-glib-aux/nm-dbus-aux.h"
#include "libnm-glib-aux/nm-io-utils.h"
#include "libnm-glib-aux/nm-logging-base.h"
#include "libnm-glib-aux/nm-shared-utils.h"
#include "libnm-glib-aux/nm-time-utils.h"
#include "libnm-base/nm-sudo-utils.h"
/* nm-sudo doesn't link with libnm-core nor libnm-base, but these headers
* can be used independently. */
@ -37,30 +37,35 @@ typedef struct {
} PendingJobData;
struct _GlobalData {
GCancellable * quit_cancellable;
GDBusConnection *dbus_connection;
GSource * source_sigterm;
GCancellable * quit_cancellable;
GSource *source_sigterm;
CList pending_jobs_lst_head;
GSource *source_idle_timeout;
char * name_owner;
guint name_owner_changed_id;
guint service_regist_id;
gint64 start_timestamp_msec;
guint32 timeout_msec;
bool name_owner_initialized;
bool name_requested;
char *name_owner;
gint64 start_timestamp_msec;
guint name_owner_changed_id;
guint service_regist_id;
guint32 timeout_msec;
bool name_owner_initialized;
/* This is controlled by $NM_SUDO_NO_AUTH_FOR_TESTING. It disables authentication
* of the request, so it is ONLY for testing. */
bool no_auth_for_testing;
bool name_requested;
bool reject_new_requests;
bool is_shutting_down_quitting;
bool is_shutting_down_timeout;
bool is_shutting_down_cleanup;
bool shutdown_quitting;
bool shutdown_timeout;
};
/*****************************************************************************/
@ -136,7 +141,7 @@ _signal_callback_term(gpointer user_data)
_LOGD("sigterm received (%s)",
c_list_is_empty(&gl->pending_jobs_lst_head) ? "quit mainloop" : "cancel operations");
gl->is_shutting_down_quitting = TRUE;
gl->shutdown_quitting = TRUE;
g_cancellable_cancel(gl->quit_cancellable);
return G_SOURCE_CONTINUE;
}
@ -417,7 +422,7 @@ _idle_timeout_cb(gpointer user_data)
_LOGT("idle-timeout: expired");
nm_clear_g_source_inst(&gl->source_idle_timeout);
gl->is_shutting_down_timeout = TRUE;
gl->shutdown_timeout = TRUE;
return G_SOURCE_CONTINUE;
}
@ -426,10 +431,7 @@ _idle_timeout_restart(GlobalData *gl)
{
nm_clear_g_source_inst(&gl->source_idle_timeout);
if (gl->is_shutting_down_quitting)
return;
if (gl->is_shutting_down_cleanup)
if (gl->shutdown_quitting)
return;
if (!c_list_is_empty(&gl->pending_jobs_lst_head))
@ -475,7 +477,7 @@ _pending_job_register_object(GlobalData *gl, GObject *obj)
PendingJobData *idle_data;
/* if we just hit the timeout, we can ignore it. */
gl->is_shutting_down_timeout = FALSE;
gl->shutdown_timeout = FALSE;
if (nm_clear_g_source_inst(&gl->source_idle_timeout))
_LOGT("idle-timeout: suspend timeout for pending request");
@ -514,8 +516,8 @@ _bus_release_name(GlobalData *gl)
if (!gl->name_requested)
return FALSE;
gl->name_requested = FALSE;
gl->is_shutting_down_quitting = TRUE;
gl->name_requested = FALSE;
gl->shutdown_quitting = TRUE;
_LOGT("shutdown: release-name");
@ -565,6 +567,8 @@ _initial_setup(GlobalData *gl)
gl->source_sigterm = nm_g_unix_signal_add_source(SIGTERM, _signal_callback_term, gl);
}
/*****************************************************************************/
int
main(int argc, char **argv)
{
@ -619,7 +623,7 @@ main(int argc, char **argv)
* Let's fake a shutdown signal, and still process the request below. */
if (!g_cancellable_is_cancelled(gl->quit_cancellable))
exit_code = EXIT_FAILURE;
gl->is_shutting_down_quitting = TRUE;
gl->shutdown_quitting = TRUE;
if (gl->name_requested) {
/* We requested a name, but something went wrong. Below we will release
@ -633,14 +637,15 @@ main(int argc, char **argv)
}
while (TRUE) {
if (gl->is_shutting_down_quitting)
if (gl->shutdown_quitting)
_bus_release_name(gl);
if (!c_list_is_empty(&gl->pending_jobs_lst_head)) {
/* we must first reply to all requests. No matter what. */
} else if (gl->is_shutting_down_quitting || gl->is_shutting_down_timeout) {
} else if (gl->shutdown_quitting || gl->shutdown_timeout) {
/* we either hit the idle timeout or received SIGTERM. Note that
* if we received an idle-timeout and the very moment afterwards
* a new request, then _bus_method_call() will clear gl->is_shutting_down_timeout
* a new request, then _bus_method_call() will clear gl->shutdown_timeout
* (via _pending_job_register_object()). */
if (!_bus_release_name(gl))
break;
@ -652,7 +657,7 @@ main(int argc, char **argv)
done:
_LOGD("shutdown: cleanup");
gl->is_shutting_down_cleanup = TRUE;
gl->shutdown_quitting = TRUE;
g_cancellable_cancel(gl->quit_cancellable);
nm_assert(c_list_is_empty(&gl->pending_jobs_lst_head));
@ -665,19 +670,19 @@ done:
g_dbus_connection_signal_unsubscribe(gl->dbus_connection,
nm_steal_int(&gl->name_owner_changed_id));
}
nm_clear_g_source_inst(&gl->source_sigterm);
nm_clear_g_source_inst(&gl->source_idle_timeout);
nm_clear_g_free(&gl->name_owner);
nm_g_main_context_iterate_ready(NULL);
if (gl->dbus_connection) {
g_dbus_connection_flush_sync(gl->dbus_connection, NULL, NULL);
g_clear_object(&gl->dbus_connection);
nm_g_main_context_iterate_ready(NULL);
}
nm_clear_g_cancellable(&gl->quit_cancellable);
nm_g_main_context_iterate_ready(NULL);
nm_clear_g_free(&gl->name_owner);
nm_clear_g_source_inst(&gl->source_sigterm);
nm_clear_g_source_inst(&gl->source_idle_timeout);
g_clear_object(&gl->quit_cancellable);
_LOGD("exit (%d)", exit_code);
return exit_code;