]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #12013 from yuwata/fix-switchroot-11997
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 2 Apr 2019 14:06:07 +0000 (16:06 +0200)
committerGitHub <noreply@github.com>
Tue, 2 Apr 2019 14:06:07 +0000 (16:06 +0200)
core: on switching root do not emit device state change based on enumeration results

1  2 
src/core/dbus-manager.c
src/core/device.c
src/core/main.c
src/core/manager.c
src/core/manager.h

diff --combined src/core/dbus-manager.c
index 475c9194acf62ece6bc4bc02b277ee47fa8e2125,c52f94c8f229dd77d3b3d807dbf2a3d708e8e543..1c1f4dcd0691678eedb6b835ee3db1a643bf8720
@@@ -334,25 -334,8 +334,25 @@@ static int bus_load_unit_by_name(Manage
          return manager_load_unit(m, name, NULL, error, ret_unit);
  }
  
 -static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
 +static int reply_unit_path(Unit *u, sd_bus_message *message, sd_bus_error *error) {
          _cleanup_free_ char *path = NULL;
 +        int r;
 +
 +        assert(u);
 +        assert(message);
 +
 +        r = mac_selinux_unit_access_check(u, message, "status", error);
 +        if (r < 0)
 +                return r;
 +
 +        path = unit_dbus_path(u);
 +        if (!path)
 +                return log_oom();
 +
 +        return sd_bus_reply_method_return(message, "o", path);
 +}
 +
 +static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
          Manager *m = userdata;
          const char *name;
          Unit *u;
          if (r < 0)
                  return r;
  
 -        r = mac_selinux_unit_access_check(u, message, "status", error);
 -        if (r < 0)
 -                return r;
 -
 -        path = unit_dbus_path(u);
 -        if (!path)
 -                return -ENOMEM;
 -
 -        return sd_bus_reply_method_return(message, "o", path);
 +        return reply_unit_path(u, message, error);
  }
  
  static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
 -        _cleanup_free_ char *path = NULL;
          Manager *m = userdata;
          pid_t pid;
          Unit *u;
          if (!u)
                  return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
  
 -        r = mac_selinux_unit_access_check(u, message, "status", error);
 -        if (r < 0)
 -                return r;
 -
 -        path = unit_dbus_path(u);
 -        if (!path)
 -                return -ENOMEM;
 -
 -        return sd_bus_reply_method_return(message, "o", path);
 +        return reply_unit_path(u, message, error);
  }
  
  static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userdata, sd_bus_error *error) {
  }
  
  static int method_get_unit_by_control_group(sd_bus_message *message, void *userdata, sd_bus_error *error) {
 -        _cleanup_free_ char *path = NULL;
          Manager *m = userdata;
          const char *cgroup;
          Unit *u;
          if (!u)
                  return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup);
  
 -        r = mac_selinux_unit_access_check(u, message, "status", error);
 -        if (r < 0)
 -                return r;
 -
 -        path = unit_dbus_path(u);
 -        if (!path)
 -                return -ENOMEM;
 -
 -        return sd_bus_reply_method_return(message, "o", path);
 +        return reply_unit_path(u, message, error);
  }
  
  static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
 -        _cleanup_free_ char *path = NULL;
          Manager *m = userdata;
          const char *name;
          Unit *u;
          if (r < 0)
                  return r;
  
 -        r = mac_selinux_unit_access_check(u, message, "status", error);
 -        if (r < 0)
 -                return r;
 -
 -        path = unit_dbus_path(u);
 -        if (!path)
 -                return -ENOMEM;
 -
 -        return sd_bus_reply_method_return(message, "o", path);
 +        return reply_unit_path(u, message, error);
  }
  
  static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
@@@ -556,26 -574,6 +556,26 @@@ static int method_reload_or_try_restart
          return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error);
  }
  
 +static int method_enqueue_unit_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
 +        Manager *m = userdata;
 +        const char *name;
 +        Unit *u;
 +        int r;
 +
 +        assert(message);
 +        assert(m);
 +
 +        r = sd_bus_message_read(message, "s", &name);
 +        if (r < 0)
 +                return r;
 +
 +        r = manager_load_unit(m, name, NULL, error, &u);
 +        if (r < 0)
 +                return r;
 +
 +        return bus_unit_method_enqueue_job(message, u, error);
 +}
 +
  static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) {
          Manager *m = userdata;
          const char *old_name;
@@@ -957,7 -955,7 +957,7 @@@ static int method_start_transient_unit(
                  return r;
  
          /* Finally, start it */
 -        return bus_unit_queue_job(message, u, JOB_START, mode, false, error);
 +        return bus_unit_queue_job(message, u, JOB_START, mode, 0, error);
  }
  
  static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@@ -1492,7 -1490,7 +1492,7 @@@ static int method_kexec(sd_bus_message 
  }
  
  static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
-         char *ri = NULL, *rt = NULL;
+         _cleanup_free_ char *ri = NULL, *rt = NULL;
          const char *root, *init;
          Manager *m = userdata;
          struct statvfs svfs;
  
          if (!isempty(init)) {
                  ri = strdup(init);
-                 if (!ri) {
-                         free(rt);
+                 if (!ri)
                          return -ENOMEM;
-                 }
          }
  
-         free(m->switch_root);
-         m->switch_root = rt;
-         free(m->switch_root_init);
-         m->switch_root_init = ri;
+         free_and_replace(m->switch_root, rt);
+         free_and_replace(m->switch_root_init, ri);
  
          m->objective = MANAGER_SWITCH_ROOT;
  
@@@ -2555,7 -2548,6 +2550,7 @@@ const sd_bus_vtable bus_manager_vtable[
          SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
          SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
          SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
 +        SD_BUS_METHOD("EnqueueUnitJob", "sss", "uososa(uosos)", method_enqueue_unit_job, SD_BUS_VTABLE_UNPRIVILEGED),
          SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
          SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
          SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
diff --combined src/core/device.c
index 771239f53b60cf5bcf0f544e563b535bba4f94b9,382c38049805e789c6c9923d86bcc392f41193e6..9f7caa49ec2448a573dbdaa0e0d88c530bcc2b73
@@@ -433,7 -433,7 +433,7 @@@ static int device_add_udev_wants(Unit *
                          if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */
                                  continue;
  
 -                        r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, &error, NULL);
 +                        r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, NULL, &error, NULL);
                          if (r < 0)
                                  log_unit_warning_errno(u, r, "Failed to enqueue SYSTEMD_WANTS= job, ignoring: %s", bus_error_message(&error, r));
                  }
@@@ -666,9 -666,13 +666,13 @@@ static void device_found_changed(Devic
  }
  
  static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) {
+         Manager *m;
          assert(d);
  
-         if (MANAGER_IS_RUNNING(UNIT(d)->manager)) {
+         m = UNIT(d)->manager;
+         if (MANAGER_IS_RUNNING(m) && (m->honor_device_enumeration || MANAGER_IS_USER(m))) {
                  DeviceFound n, previous;
  
                  /* When we are already running, then apply the new mask right-away, and trigger state changes
diff --combined src/core/main.c
index 0ba22f815d91da3061fc015645baba1746132883,1617b237672e599c5fb4b898120fded0f91c4fc4..46db47126c6dc9c0692b6c69d2b6d4c1178a0b9f
@@@ -1908,9 -1908,8 +1908,8 @@@ static int invoke_main_loop
                          *ret_shutdown_verb = NULL;
  
                          /* Steal the switch root parameters */
-                         *ret_switch_root_dir = m->switch_root;
-                         *ret_switch_root_init = m->switch_root_init;
-                         m->switch_root = m->switch_root_init = NULL;
+                         *ret_switch_root_dir = TAKE_PTR(m->switch_root);
+                         *ret_switch_root_init = TAKE_PTR(m->switch_root_init);
  
                          return 0;
  
@@@ -2121,13 -2120,13 +2120,13 @@@ static int do_queue_default_job
  
          assert(target->load_state == UNIT_LOADED);
  
 -        r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &default_unit_job);
 +        r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, NULL, &error, &default_unit_job);
          if (r == -EPERM) {
                  log_debug_errno(r, "Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
  
                  sd_bus_error_free(&error);
  
 -                r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &default_unit_job);
 +                r = manager_add_job(m, JOB_START, target, JOB_REPLACE, NULL, &error, &default_unit_job);
                  if (r < 0) {
                          *ret_error_message = "Failed to start default target";
                          return log_emergency_errno(r, "Failed to start default target: %s", bus_error_message(&error, r));
@@@ -2380,7 -2379,8 +2379,7 @@@ int main(int argc, char *argv[]) 
          (void) prctl(PR_SET_NAME, systemd);
  
          /* Save the original command line */
 -        saved_argv = argv;
 -        saved_argc = argc;
 +        save_argc_argv(argc, argv);
  
          /* Make sure that if the user says "syslog" we actually log to the journal. */
          log_set_upgrade_syslog_to_journal(true);
diff --combined src/core/manager.c
index 6cb7d4d0d09dcf9e69626e3e7b70e96eead68fc7,3f4dbe64e301aeeef6ed5180ce37af414ada83e1..12ae911a38bac098e9464ae0aa9a91db01736e39
@@@ -292,10 -292,10 +292,10 @@@ static int manager_check_ask_password(M
  
                  m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
                  if (m->ask_password_inotify_fd < 0)
 -                        return log_error_errno(errno, "inotify_init1() failed: %m");
 +                        return log_error_errno(errno, "Failed to create inotify object: %m");
  
                  if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) {
 -                        log_error_errno(errno, "Failed to add watch on /run/systemd/ask-password: %m");
 +                        log_error_errno(errno, "Failed to watch \"/run/systemd/ask-password\": %m");
                          manager_close_ask_password(m);
                          return -errno;
                  }
@@@ -1253,7 -1253,7 +1253,7 @@@ static unsigned manager_dispatch_stop_w
                  }
  
                  /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
 -                r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
 +                r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL);
                  if (r < 0)
                          log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
          }
@@@ -1619,6 -1619,8 +1619,8 @@@ static void manager_ready(Manager *m) 
  
          /* Let's finally catch up with any changes that took place while we were reloading/reexecing */
          manager_catchup(m);
+         m->honor_device_enumeration = true;
  }
  
  static Manager* manager_reloading_start(Manager *m) {
@@@ -1730,17 -1732,9 +1732,17 @@@ int manager_startup(Manager *m, FILE *s
          return 0;
  }
  
 -int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret) {
 -        int r;
 +int manager_add_job(
 +                Manager *m,
 +                JobType type,
 +                Unit *unit,
 +                JobMode mode,
 +                Set *affected_jobs,
 +                sd_bus_error *error,
 +                Job **ret) {
 +
          Transaction *tr;
 +        int r;
  
          assert(m);
          assert(type < _JOB_TYPE_MAX);
          assert(mode < _JOB_MODE_MAX);
  
          if (mode == JOB_ISOLATE && type != JOB_START)
 -                return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
 +                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
  
          if (mode == JOB_ISOLATE && !unit->allow_isolate)
 -                return sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
 +                return sd_bus_error_setf(error, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
  
          log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
  
  
          r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, false,
                                                   IN_SET(mode, JOB_IGNORE_DEPENDENCIES, JOB_IGNORE_REQUIREMENTS),
 -                                                 mode == JOB_IGNORE_DEPENDENCIES, e);
 +                                                 mode == JOB_IGNORE_DEPENDENCIES, error);
          if (r < 0)
                  goto tr_abort;
  
                          goto tr_abort;
          }
  
 -        r = transaction_activate(tr, m, mode, e);
 +        r = transaction_activate(tr, m, mode, affected_jobs, error);
          if (r < 0)
                  goto tr_abort;
  
                         "Enqueued job %s/%s as %u", unit->id,
                         job_type_to_string(type), (unsigned) tr->anchor_job->id);
  
 -        if (_ret)
 -                *_ret = tr->anchor_job;
 +        if (ret)
 +                *ret = tr->anchor_job;
  
          transaction_free(tr);
          return 0;
@@@ -1793,7 -1787,7 +1795,7 @@@ tr_abort
          return r;
  }
  
 -int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) {
 +int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **ret) {
          Unit *unit = NULL;  /* just to appease gcc, initialization is not really necessary */
          int r;
  
                  return r;
          assert(unit);
  
 -        return manager_add_job(m, type, unit, mode, e, ret);
 +        return manager_add_job(m, type, unit, mode, affected_jobs, e, ret);
  }
  
 -int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
 +int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret) {
          _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
          int r;
  
          assert(name);
          assert(mode < _JOB_MODE_MAX);
  
 -        r = manager_add_job_by_name(m, type, name, mode, &error, ret);
 +        r = manager_add_job_by_name(m, type, name, mode, affected_jobs, &error, ret);
          if (r < 0)
                  return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r));
  
@@@ -1847,7 -1841,7 +1849,7 @@@ int manager_propagate_reload(Manager *m
          /* Failure in adding individual dependencies is ignored, so this always succeeds. */
          transaction_add_propagate_reload_jobs(tr, unit, tr->anchor_job, mode == JOB_IGNORE_DEPENDENCIES, e);
  
 -        r = transaction_activate(tr, m, mode, e);
 +        r = transaction_activate(tr, m, mode, NULL, e);
          if (r < 0)
                  goto tr_abort;
  
@@@ -2137,16 -2131,6 +2139,16 @@@ void manager_clear_jobs(Manager *m) 
                  job_finish_and_invalidate(j, JOB_CANCELED, false, false);
  }
  
 +void manager_unwatch_pid(Manager *m, pid_t pid) {
 +        assert(m);
 +
 +        /* First let's drop the unit keyed as "pid". */
 +        (void) hashmap_remove(m->watch_pids, PID_TO_PTR(pid));
 +
 +        /* Then, let's also drop the array keyed by -pid. */
 +        free(hashmap_remove(m->watch_pids, PID_TO_PTR(-pid)));
 +}
 +
  static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
          Manager *m = userdata;
          Job *j;
@@@ -2557,7 -2541,7 +2559,7 @@@ static void manager_start_target(Manage
  
          log_debug("Activating special unit %s", name);
  
 -        r = manager_add_job_by_name(m, JOB_START, name, mode, &error, NULL);
 +        r = manager_add_job_by_name(m, JOB_START, name, mode, NULL, &error, NULL);
          if (r < 0)
                  log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
  }
@@@ -3074,7 -3058,7 +3076,7 @@@ void manager_send_unit_plymouth(Manage
          }
  
          if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
 -                if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
 +                if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno))
                          log_error_errno(errno, "connect() failed: %m");
                  return;
          }
  
          errno = 0;
          if (write(fd, message, n + 1) != n + 1)
 -                if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
 +                if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno))
                          log_error_errno(errno, "Failed to write Plymouth message: %m");
  }
  
@@@ -3149,6 -3133,9 +3151,9 @@@ int manager_serialize
          (void) serialize_bool(f, "taint-logged", m->taint_logged);
          (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
  
+         /* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */
+         (void) serialize_bool(f, "honor-device-enumeration", !switching_root);
          t = show_status_to_string(m->show_status);
          if (t)
                  (void) serialize_item(f, "show-status", t);
@@@ -3377,6 -3364,15 +3382,15 @@@ int manager_deserialize(Manager *m, FIL
                          else
                                  m->service_watchdogs = b;
  
+                 } else if ((val = startswith(l, "honor-device-enumeration="))) {
+                         int b;
+                         b = parse_boolean(val);
+                         if (b < 0)
+                                 log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val);
+                         else
+                                 m->honor_device_enumeration = b;
                  } else if ((val = startswith(l, "show-status="))) {
                          ShowStatus s;
  
@@@ -3567,6 -3563,11 +3581,11 @@@ int manager_reload(Manager *m) 
          assert(m->n_reloading > 0);
          m->n_reloading--;
  
+         /* On manager reloading, device tag data should exists, thus, we should honor the results of device
+          * enumeration. The flag should be always set correctly by the serialized data, but it may fail. So,
+          * let's always set the flag here for safety. */
+         m->honor_device_enumeration = true;
          manager_ready(m);
  
          m->send_reloading_done = true;
@@@ -3795,7 -3796,7 +3814,7 @@@ static bool generator_path_any(const ch
          return found;
  }
  
 -static const char* system_env_generator_binary_paths[] = {
 +static const char *const system_env_generator_binary_paths[] = {
          "/run/systemd/system-environment-generators",
          "/etc/systemd/system-environment-generators",
          "/usr/local/lib/systemd/system-environment-generators",
          NULL
  };
  
 -static const char* user_env_generator_binary_paths[] = {
 +static const char *const user_env_generator_binary_paths[] = {
          "/run/systemd/user-environment-generators",
          "/etc/systemd/user-environment-generators",
          "/usr/local/lib/systemd/user-environment-generators",
  
  static int manager_run_environment_generators(Manager *m) {
          char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
 -        const char **paths;
 +        const char *const *paths;
          void* args[] = {
                  [STDOUT_GENERATE] = &tmp,
                  [STDOUT_COLLECT] = &tmp,
diff --combined src/core/manager.h
index 8c7bd7e231912430c70341198b1e0ee9f7ca1dc2,86b9ec202dbd68d670b734ae7a8440a08cac26cd..cdd4882a6a755616f69e08e3893b86b724e52db9
@@@ -395,6 -395,8 +395,8 @@@ struct Manager 
           * multiple times on the same unit. */
          unsigned sigchldgen;
          unsigned notifygen;
+         bool honor_device_enumeration;
  };
  
  #define MANAGER_IS_SYSTEM(m) ((m)->unit_file_scope == UNIT_FILE_SYSTEM)
@@@ -425,9 -427,9 +427,9 @@@ int manager_load_unit(Manager *m, cons
  int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
  int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
  
 -int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret);
 -int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **_ret);
 -int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret);
 +int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret);
 +int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret);
 +int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs,  Job **ret);
  int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e);
  
  void manager_dump_units(Manager *s, FILE *f, const char *prefix);
@@@ -437,8 -439,6 +439,8 @@@ int manager_get_dump_string(Manager *m
  
  void manager_clear_jobs(Manager *m);
  
 +void manager_unwatch_pid(Manager *m, pid_t pid);
 +
  unsigned manager_dispatch_load_queue(Manager *m);
  
  int manager_default_environment(Manager *m);