#include "alloc-util.h"
#include "architecture.h"
#include "argv-util.h"
+#include "cgroup-util.h"
#include "dirent-util.h"
#include "env-file.h"
#include "env-util.h"
return FLAGS_SET(flags, POSIX_SPAWN_SETCGROUP);
}
- if (!(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r)))
+ if (ERRNO_IS_NOT_SUPPORTED(r)) {
+ /* clone3() could also return EOPNOTSUPP if the target cgroup is in threaded mode. */
+ if (cgroup && cg_is_threaded(cgroup) > 0)
+ return -EUCLEAN;
+
+ /* clone3() not available? */
+ } else if (!ERRNO_IS_PRIVILEGE(r))
return -r;
/* Compiled on a newer host, or seccomp&friends blocking clone3()? Fallback, but need to change the
r = cg_attach_everywhere(params->cgroup_supported, p, 0, NULL, NULL);
if (r == -EUCLEAN) {
*exit_status = EXIT_CGROUP;
- return log_exec_error_errno(context, params, r, "Failed to attach process to cgroup %s "
+ return log_exec_error_errno(context, params, r,
+ "Failed to attach process to cgroup '%s', "
"because the cgroup or one of its parents or "
- "siblings is in the threaded mode: %m", p);
+ "siblings is in the threaded mode.", p);
}
if (r < 0) {
*exit_status = EXIT_CGROUP;
environ,
cg_unified() > 0 ? subcgroup_path : NULL,
&pidref);
+ if (r == -EUCLEAN && subcgroup_path)
+ return log_unit_error_errno(unit, r,
+ "Failed to spawn process into cgroup '%s', because the cgroup "
+ "or one of its parents or siblings is in the threaded mode.",
+ subcgroup_path);
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to spawn executor: %m");
/* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever