Bruno Haible via Gnulib discussion list <[email protected]> writes:

> In a testdir of module 'posix_spawn_file_actions_addclose', I see this test
> failure on NetBSD 10.0:
>
> FAIL: test-posix_spawn_file_actions_addclose
> ============================================
>
> ../../gnulib-tests/test-posix_spawn_file_actions_addclose.c:63: assertion 
> 'posix_spawn_file_actions_addclose (&actions, bad_fd) == EBADF' failed
> FAIL test-posix_spawn_file_actions_addclose (exit status: 134)
>
> The cause is that
>   * NetBSD does not reject out-of-range fd arguments, see in the
>     NetBSD source code, at
>     src/lib/libc/gen/posix_spawn_fileactions.c, function
>     posix_spawn_file_actions_addclose.
>   * The configure test does not mark
>     posix_spawn_file_actions_addclose as broken.

Same with OpenBSD and FreeBSD [1][2].

I was going to report it as a bug for all of them, except for OpenBSD
which I don't have much luck reporting bugs with. However, this behavior
is not required by POSIX [3]:

    The posix_spawn_file_actions_addopen() function shall fail if:
    
    [EBADF]
        The value specified by fildes is negative or greater than or
        equal to {OPEN_MAX}.
    
    The posix_spawn_file_actions_addclose() function shall fail if:
    
    [EBADF]
        The value specified by fildes is negative.

In fact, I think that glibc's behavior may violate POSIX requirements:

     It shall not be considered an error for the fildes argument passed
     to these functions to specify a file descriptor for which the
     specified operation could not be performed at the time of the call.
     Any such error shall be detected when the associated file actions
     object is later used during a posix_spawn() or posix_spawnp()
     operation.

One might have code that does the following:

    posix_spawn
    posix_spawn_file_actions_t actions;
    int result;
    if ((result = posix_spawn_file_actions_init (&actions))
        || (result = posix_spawn_file_actions_addclose (&actions,
                                                        getdtablesize ())))
         error (EXIT_FAILURE, result, _("failed to setup posix_spawn"));
    struct rlimit fdlimit = { .rlim_cur = getdtablesize () + 1,
                              .rlim_max = getdtablesize () + 1 };
    if (setrlimit (RLIMIT_NOFILE, &fdlimit) < 0)
      error (EXIT_FAILURE, errno,
             _("failed to increase file descriptor limit"));
    int result = posix_spawnp (...);

Strange ordering, in my opinion, but POSIX wants the
posix_spawn_file_actions_addclose() to succeed since after the setrlimit
the close may be valid depending on whether the file descriptor gets
opened somewhere in else in the program.

Collin

[1] 
https://github.com/openbsd/src/blob/9abc5df53d8ad6b65dbd35b89ed94f73e2fc58da/lib/libc/gen/posix_spawn.c#L345
[2] 
https://github.com/freebsd/freebsd-src/blob/86b259a28a1a47b0506c519b17d8adb67d4a0b0d/lib/libc/gen/posix_spawn.c#L435
[3] 
https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addclose.html

P.S. All of the BSD spawn implementations are roughly the same. OpenBSD
and NetBSD used FreeBSD's implementation. NetBSD seems to have diverged
a bit, though.

Reply via email to