Skip to content

Commit

Permalink
imp: exec: wait for empty cgroup before exiting
Browse files Browse the repository at this point in the history
Problem: The IMP immediately exits after waitpid(2) returns for its
immediate child, but this could leave extra processes running in the
job's cgroup.

Wait for the job cgroup to be empty before allowing the IMP to exit.

An empty cgroup is considered one in which the only process is
cgroup.procs is the IMP itself.
  • Loading branch information
grondo committed Nov 1, 2024
1 parent ec3ce12 commit 3feae11
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 0 deletions.
23 changes: 23 additions & 0 deletions src/imp/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,5 +241,28 @@ int cgroup_kill (struct cgroup_info *cgroup, int sig)
return count;
}

int cgroup_wait_for_empty (struct cgroup_info *cgroup)
{
int n;

/* Only wait for empty cgroup if cgroup kill is enabled.
*/
if (!cgroup->use_cgroup_kill)
return 0;

while ((n = cgroup_kill (cgroup, 0)) > 0) {
/* Note: inotify/poll() do not work on the cgroup.procs virtual
* file. Therefore, wait at most 1s and check to see if the cgroup
* is empty again. If the job execution system requests a signal to
* be delivered then the sleep will be interrupted, in which case a
* a small delay is added in hopes that any terminated processes
* will have been removed from cgroup.procs by then.
*/
if (usleep (1e6) < 0 && errno == EINTR)
usleep (2000);
}
return 0;
}

/* vi: ts=4 sw=4 expandtab
*/
4 changes: 4 additions & 0 deletions src/imp/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ void cgroup_info_destroy (struct cgroup_info *cgroup);
*/
int cgroup_kill (struct cgroup_info *cgroup, int sig);

/* Wait for all processes in cgroup (except this one) to exit.
*/
int cgroup_wait_for_empty (struct cgroup_info *cgroup);

#endif /* !HAVE_IMP_CGROUP_H */
3 changes: 3 additions & 0 deletions src/imp/exec/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ int imp_exec_privileged (struct imp_state *imp, struct kv *kv)
imp_die (1, "waitpid: %s", strerror (errno));
}

if (cgroup_wait_for_empty (exec->imp->cgroup) < 0)
imp_warn ("error waiting for processes in job cgroup");

#if HAVE_PAM
/* Call privliged IMP plugins/containment finalization */
if (imp_supports_pam (exec))
Expand Down

0 comments on commit 3feae11

Please sign in to comment.