[PATCH v7 4/8] linux: Add posix_spawnattr_{get, set}cgroup_np (BZ 26731)

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Fri Aug 11 15:31:20 GMT 2023



On 11/08/23 07:51, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
> 
>> These function allow to posix_spawn and posix_spawnp to use
>> CLONE_INTO_CGROUP with clone3, allowing the child process to
>> be created in a different version 2 cgroup.  These are GNU
>> extensions that are available only for Linux, and also only
>> for the architectures that implement clone3 wrapper
>> (HAVE_CLONE3_WRAPPER).
>>
>> To create a process on a different cgroupv2, one can use the:
>>
>>   posix_spawnattr_t attr;
>>   posix_spawnattr_init (&attr);
>>   posix_spawnattr_setflags (&attr, POSIX_SPAWN_SETCGROUP);
>>   posix_spawnattr_setcgroup_np (&attr, cgroup);
>>   posix_spawn (...)
> 
> Why are both POSIX_SPAWN_SETCGROUP and posix_spawnattr_setcgroup_np
> needed?  Couldn't the latter imply the former?

Besides being orthogonal with the other standard options, it allows
the called to just set/reset a flag in a posix_spawnattr_t to enable
disable the options instead of create/destroy a new attribute for
each posix_spawn call.

> 
>> There is no fallback is either clone3 does not support the flag
>> or if the architecture does not provide the clone3 wrapper, in
>> this case posix_spawn returns ENOTSUP.
> 
> I think this really should be added to the manual, mayb
> 
> It's also not clear to me how you would probe for support properly.
> The spawn operation might fail for other reasons.
> 
> I wonder if we have to probe as part of the 

Some comments seems to be truncated.  For probing, posix_spawnattr_setflags
fails with invalid flags, so trying to use POSIX_SPAWN_SETCGROUP if is
is not support should return EINVAL.

About the manual, I can add something but since we do not any sort of
posix_spawn it would require to add a lot of stubs.

> 
>> diff --git a/sysdeps/unix/sysv/linux/bits/spawn_ext.h b/sysdeps/unix/sysv/linux/bits/spawn_ext.h
>> new file mode 100644
>> index 0000000000..3bc10ab477
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/bits/spawn_ext.h
> 
>> +/* Get the cgroupsv2 the attribute structure.  */
>> +extern int posix_spawnattr_getcgroup_np (const posix_spawnattr_t *
>> +					 __restrict __attr,
>> +					 int *__cgroup)
>> +     __THROW __nonnull ((1, 2));
>> +
>> +/* Store scheduling parameters in the attribute structure.  */
>> +extern int posix_spawnattr_setcgroup_np (posix_spawnattr_t *__restrict __attr,
>> +					 int __cgroup)
>> +     __THROW __nonnull ((1));
> 
> Second comment seems wrong.

Indeed, and there is no need of __restrict here.  Also on 
posix_spawnattr_getcgroup_np it should have a __restrict for the
cgroup argument.

> 
>> diff --git a/sysdeps/unix/sysv/linux/tst-spawn-cgroup.c b/sysdeps/unix/sysv/linux/tst-spawn-cgroup.c
>> new file mode 100644
>> index 0000000000..6dba30ab29
>> --- /dev/null
>> +++ b/sysdeps/unix/sysv/linux/tst-spawn-cgroup.c
>> @@ -0,0 +1,216 @@
>> +/* Tests for posix_spawn cgroup extension.
> 
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <http://www.gnu.org/licenses/>.  */
> 
> Should be “https://”.

Ack.

> 
>> +#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
> 
> Missing space after “type”.

Ack.

> 
>> +static char *
>> +get_cgroup (void)
>> +{
>> +  FILE *f = fopen ("/proc/self/cgroup", "re");
>> +  if (f == NULL)
>> +    FAIL_UNSUPPORTED ("no cgroup defined for the process");
> 
> Maybe add %m here.

Ack.

> 
>> +/* Called on process re-execution.  */
>> +_Noreturn static void
>> +handle_restart (int argc, char *argv[])
>> +{
>> +  assert (argc == 1);
>> +  char *newcgroup = argv[0];
>> +
>> +  char *current_cgroup = get_cgroup ();
>> +  TEST_VERIFY_EXIT (current_cgroup != NULL);
>> +  TEST_COMPARE_STRING (newcgroup, current_cgroup);
>> +  exit (EXIT_SUCCESS);
>> +}
> 
> I think the exit (EXIT_SUCCESS) masks failures because after execve, the
> shared mapping with failure status does not exist.

The TEST_VERIFY_EXIT should trigger the waitid checks, but you are right
for TEST_COMPARE_STRING. I removed the exit to let the support/test-driver.c
return the expected exit code.

> 
>> +static int
>> +create_new_cgroup (char **newcgroup)
>> +{
>> +  struct statfs fs;
>> +  if (statfs (CGROUPFS, &fs) < 0)
>> +    {
>> +      if (errno == ENOENT)
>> +	FAIL_UNSUPPORTED ("not cgroupv2 mount found");
>> +      FAIL_EXIT1 ("statfs (%s): %m\n", CGROUPFS);
> 
> “no[] cgroupv2 found?”

Ack.

> 
>> +    }
>> +
>> +  if (!F_TYPE_EQUAL (fs.f_type, CGROUP2_SUPER_MAGIC))
>> +    FAIL_UNSUPPORTED ("%s is not a cgroupv2", CGROUPFS);
> 
> This could print fs.f_type.

Ack.


More information about the Libc-alpha mailing list