Browse Source

load-service: minor refactoring

Add a separate function to check whether provided settings for a reload
are compatible with the existing service.
Davin McCall 10 months ago
parent
commit
bba3dc1269
1 changed files with 90 additions and 73 deletions
  1. 90 73
      src/load-service.cc

+ 90 - 73
src/load-service.cc

@@ -224,6 +224,92 @@ static void update_command_and_dependencies(base_process_service *service,
     }
 }
 
+// Check that the provided settings are compatible / ok to be applied to the specified (already loaded)
+// service.
+// Returns: true if a new service record must be created, false otherwise
+static bool check_settings_for_reload(service_record *service,
+        dinit_load::service_settings_wrapper<prelim_dep> &settings)
+{
+    using namespace dinit_load;
+
+    const std::string &name = service->get_name();
+
+    // To begin, assume a new record is needed
+    bool create_new_record = true;
+
+    if (service->get_state() != service_state_t::STOPPED) {
+        // Can not change type of a running service.
+        if (settings.service_type != service->get_type()) {
+            throw service_load_exc(name, "cannot change type of non-stopped service.");
+        }
+        // Can not alter a starting/stopping service, at least for now.
+        if (service->get_state() != service_state_t::STARTED) {
+            throw service_load_exc(name,
+                    "cannot alter settings for service which is currently starting/stopping.");
+        }
+
+        // Check validity of dependencies (if started, regular deps must be started)
+        for (auto &new_dep : settings.depends) {
+            if (new_dep.dep_type == dependency_type::REGULAR) {
+                if (new_dep.to->get_state() != service_state_t::STARTED) {
+                    throw service_load_exc(name,
+                            std::string("cannot add non-started dependency '")
+                                + new_dep.to->get_name() + "'.");
+                }
+            }
+        }
+
+        // Cannot change certain flags
+        auto current_flags = service->get_flags();
+        if (current_flags.starts_on_console != settings.onstart_flags.starts_on_console
+                || current_flags.shares_console != settings.onstart_flags.shares_console) {
+            throw service_load_exc(name, "cannot change starts_on_console/"
+                    "shares_console flags for a running service.");
+        }
+
+        // Cannot change pid file
+        if (service->get_type() == service_type_t::BGPROCESS) {
+            auto *bgp_service = static_cast<bgproc_service *>(service);
+            if (bgp_service->get_pid_file() != settings.pid_file) {
+                throw service_load_exc(name, "cannot change pid_file for running service.");
+            }
+        }
+
+        // Cannot change inittab_id/inittab_line
+        #if USE_UTMPX
+            if (service->get_type() == service_type_t::PROCESS) {
+                auto *proc_service = static_cast<process_service *>(service);
+                auto *svc_utmp_id = proc_service->get_utmp_id();
+                auto *svc_utmp_ln = proc_service->get_utmp_line();
+                if (strncmp(svc_utmp_id, settings.inittab_id, proc_service->get_utmp_id_size()) != 0
+                        || strncmp(svc_utmp_ln, settings.inittab_line,
+                                proc_service->get_utmp_line_size()) != 0) {
+                    throw service_load_exc(name, "cannot change inittab-id or inittab-line "
+                            "settings for running service.");
+                }
+            }
+        #endif
+
+        // Cannot change log type
+        if (value(service->get_type()).is_in(service_type_t::PROCESS, service_type_t::BGPROCESS,
+                service_type_t::SCRIPTED)) {
+            base_process_service *bps = static_cast<base_process_service *>(service);
+            if (bps->get_log_mode() != settings.log_type) {
+                throw service_load_exc(name, "cannot change log-type for running service.");
+            }
+        }
+
+        // Already started; we must replace settings on existing service record
+        create_new_record = false;
+    }
+    else if (settings.service_type == service->get_type()) {
+        // No need to create a new record if the type hasn't changed
+        create_new_record = false;
+    }
+
+    return create_new_record;
+}
+
 service_record * dirload_service_set::load_reload_service(const char *name, service_record *reload_svc,
         const service_record *avoid_circular)
 {
@@ -456,76 +542,7 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv
 
         if (reload_svc != nullptr) {
             // Make sure settings are able to be changed/are compatible
-            service_record *service = reload_svc;
-            if (service->get_state() != service_state_t::STOPPED) {
-                // Can not change type of a running service.
-                if (service_type != service->get_type()) {
-                    throw service_load_exc(name, "cannot change type of non-stopped service.");
-                }
-                // Can not alter a starting/stopping service, at least for now.
-                if (service->get_state() != service_state_t::STARTED) {
-                    throw service_load_exc(name,
-                            "cannot alter settings for service which is currently starting/stopping.");
-                }
-
-                // Check validity of dependencies (if started, regular deps must be started)
-                for (auto &new_dep : settings.depends) {
-                    if (new_dep.dep_type == dependency_type::REGULAR) {
-                        if (new_dep.to->get_state() != service_state_t::STARTED) {
-                            throw service_load_exc(name,
-                                    std::string("cannot add non-started dependency '")
-                                        + new_dep.to->get_name() + "'.");
-                        }
-                    }
-                }
-
-                // Cannot change certain flags
-                auto current_flags = service->get_flags();
-                if (current_flags.starts_on_console != settings.onstart_flags.starts_on_console
-                        || current_flags.shares_console != settings.onstart_flags.shares_console) {
-                    throw service_load_exc(name, "cannot change starts_on_console/"
-                            "shares_console flags for a running service.");
-                }
-
-                // Cannot change pid file
-                if (service->get_type() == service_type_t::BGPROCESS) {
-                    auto *bgp_service = static_cast<bgproc_service *>(service);
-                    if (bgp_service->get_pid_file() != settings.pid_file) {
-                        throw service_load_exc(name, "cannot change pid_file for running service.");
-                    }
-                }
-
-                // Cannot change inittab_id/inittab_line
-                #if USE_UTMPX
-                    if (service->get_type() == service_type_t::PROCESS) {
-                        auto *proc_service = static_cast<process_service *>(service);
-                        auto *svc_utmp_id = proc_service->get_utmp_id();
-                        auto *svc_utmp_ln = proc_service->get_utmp_line();
-                        if (strncmp(svc_utmp_id, settings.inittab_id, proc_service->get_utmp_id_size()) != 0
-                                || strncmp(svc_utmp_ln, settings.inittab_line,
-                                        proc_service->get_utmp_line_size()) != 0) {
-                            throw service_load_exc(name, "cannot change inittab-id or inittab-line "
-                                    "settings for running service.");
-                        }
-                    }
-                #endif
-
-                // Cannot change log type
-                if (value(service->get_type()).is_in(service_type_t::PROCESS, service_type_t::BGPROCESS,
-                        service_type_t::SCRIPTED)) {
-                    base_process_service *bps = static_cast<base_process_service *>(service);
-                    if (bps->get_log_mode() != settings.log_type) {
-                        throw service_load_exc(name, "cannot change log-type for running service.");
-                    }
-                }
-
-                // Already started; we must replace settings on existing service record
-                create_new_record = false;
-            }
-            else if (service_type == service->get_type()) {
-                // No need to create a new record if the type hasn't changed
-                create_new_record = false;
-            }
+            create_new_record = check_settings_for_reload(reload_svc, settings);
         }
 
         // Note, we need to be very careful to handle exceptions properly and roll back any changes that
@@ -572,8 +589,7 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv
         // if we have "before" constraints, check them now.
         for (const std::string &before_ent : settings.before_svcs) {
             service_record *before_svc;
-            if (before_ent == name)
-                throw service_cyclic_dependency(name);
+            if (before_ent == name) throw service_cyclic_dependency(name);
 
             before_svc = find_service(before_ent.c_str(), true);
             if (before_svc != nullptr) {
@@ -593,7 +609,8 @@ service_record * dirload_service_set::load_reload_service(const char *name, serv
                 }
 
                 before_deps.emplace_back(before_svc, reload_svc, dependency_type::BEFORE);
-                // (note, we may need to adjust the to-service if we create a new service record object)
+                // (note, we may need to adjust the to-service if we create a new service record object
+                // - this will be done later)
 			}
 		}