public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Florian Weimer <fweimer@redhat.com>
To: Adhemerval Zanella via Libc-alpha <libc-alpha@sourceware.org>
Subject: Re: [PATCH v3 2/4] Linux: Add close_range
Date: Tue, 09 Mar 2021 10:47:59 +0100	[thread overview]
Message-ID: <87mtvc64kw.fsf@oldenburg.str.redhat.com> (raw)
In-Reply-To: <20201223163651.2634504-2-adhemerval.zanella@linaro.org> (Adhemerval Zanella via Libc-alpha's message of "Wed, 23 Dec 2020 13:36:49 -0300")

* Adhemerval Zanella via Libc-alpha:

> diff --git a/manual/llio.texi b/manual/llio.texi
> index c0a53e1a6e..ceb18ac89a 100644
> --- a/manual/llio.texi
> +++ b/manual/llio.texi
> @@ -284,6 +284,44 @@ of trying to close its underlying file descriptor with @code{close}.
>  This flushes any buffered output and updates the stream object to
>  indicate that it is closed.
>  
> +@deftypefun int close_range (unsigned int @var{lowfd}, unsigned int @var{maxfd}, int @var{flags})
> +@standards{Linux, unistd.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{@acsfd{}}}
> +@c This is a syscall for Linux v5.9.  There is no fallback emulation for
> +@c older kernels.
> +
> +The function @code{clode_range} closes the file descriptor from @var{lowfd}
> +to @var{maxfd} (inclusive).  This function is similar to call @code{close} in
> +specified file descriptor range depending on the @var{flags}.
> +
> +The @var{flags} add options on how the files are closes.  Linux currently
> +supports:.

Spurios “.” at end of line.

> +@vtable @code
> +@item CLOSE_RANGE_UNSHARE
> +Unshare the file descriptor table before closing file descriptors.
> +@end vtable
> +
> +The normal return value from @code{close_range} is @math{0}; a value
> +of @math{-1} is returned in case of failure.  The following @code{errno} error
> +conditions are defined for this function:
> +
> +@table @code
> +@item EINVAL
> +The @var{lowfd} value is larger than @var{maxfd} or an unsupported @var{flags}
> +is used.
> +
> +@item ENOMEM
> +Either there is not enough memory for the operation, or the process is
> +out of address space.
> +
> +@item EMFILE
> +The process has too many files open.
> +The maximum number of file descriptors is controlled by the
> +@end table
> +@end deftypefun

The ENOMEM and EMFILE descriptions are not really clear in this context.
Are these failures only possible with CLOSE_RANGE_UNSHARE?

It may make sense to mention the lack of emulation (so that callers have
to be aware of ENOSYS for the time being) and that the function is
specific to Linux.

Based on the description, it is not clear what happens if the range
contains closed descriptors.  Maybe mention that already-closed
descriptors are simply skipped?

> index c35f783e2a..e2a6fa763f 100644
> --- a/sysdeps/unix/sysv/linux/Versions
> +++ b/sysdeps/unix/sysv/linux/Versions
> @@ -169,6 +169,9 @@ libc {
>    }
>    GLIBC_2.32 {
>    }
> +  GLIBC_2.33 {
> +    close_range;
> +  }

Needs to be GLIBC_2.34 now.  Also the copyright year needs adjusting.

> diff --git a/sysdeps/unix/sysv/linux/bits/unistd_ext.h b/sysdeps/unix/sysv/linux/bits/unistd_ext.h
> index c315cc5cb8..799c59512c 100644
> --- a/sysdeps/unix/sysv/linux/bits/unistd_ext.h
> +++ b/sysdeps/unix/sysv/linux/bits/unistd_ext.h
> @@ -33,4 +33,15 @@
>     not detached and has not been joined.  */
>  extern __pid_t gettid (void) __THROW;
>  
> +/* Unshare the file descriptor table before closing file descriptors.  */
> +#define CLOSE_RANGE_UNSHARE     (1U << 1)

Needs to be indented.

Please include <linux/close_range.h> if available.  It's a separate
header so that we can use it.

I think if you do that, the consistency check won't add much value
because it can't really test anything.

> +/* Close all file descriptors in the range FD up to MAX_FD.  The flag FLAGS
> +   are define by the CLOSE_RANGE prefix.  This function behaves like close
> +   on the range, but in a fail-safe where it will either fail and not close
> +   any file descriptor or close all of them.  Returns 0 on successor or -1
> +   for failure (and sets errno accordingly).  */
> +extern int close_range (unsigned int __fd, unsigned int __max_fd,
> +			int __flags) __THROW;
> +
>  #endif

Maybe add /* __USE_GNU */ to the #endif, given that it's now at a
distance from the #ifdef.

> diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c
> new file mode 100644
> index 0000000000..131cf27c72
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-close_range.c
> @@ -0,0 +1,222 @@

> +#define NFDS 100
> +
> +static int
> +open_multiple_temp_files (void)
> +{
> +  /* Check if the temporary file descriptor has no no gaps.  */
> +  int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
> +  for (int i = 1; i <= NFDS; i++)
> +    TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600),
> +		  lowfd + i);
> +  return lowfd;
> +}

Okay, this ensures that there are no gaps.

> +
> +static void
> +close_range_test_common (int lowfd, unsigned int flags)
> +{
> +  const int maximum_fd = lowfd + NFDS;
> +  const int half_fd = maximum_fd / 2;
> +  const int gap_1 = maximum_fd - 8;

I think half_fd should be should be lowfd + NFDS / 2.

> +_Noreturn static int
> +close_range_test_fn (void *arg)
> +{
> +  int lowfd = (int) ((uintptr_t) arg);
> +  close_range_test_common (lowfd, 0);
> +  exit (EXIT_SUCCESS);
> +}
> +
> +/* Check if a clone_range on a subprocess created with CLONE_FILES close
> +   the shared file descriptor table entries in the parent.  */
> +static void
> +close_range_test_subprocess (void)
> +{
> +  struct support_descriptors *descrs = support_descriptors_list ();
> +
> +  /* Check if the temporary file descriptor has no no gaps.  */
> +  int lowfd = open_multiple_temp_files ();
> +
> +  enum { stack_size = 4096 };
> +  DEFINE_STACK (stack, stack_size);
> +  pid_t pid = xclone (close_range_test_fn, (void*) (uintptr_t) lowfd, stack,
> +		      stack_size, CLONE_FILES | SIGCHLD);

stack_size is too small, I think.  Future error checking (possible with
clone3) would lead to failures.

> +static void
> +close_range_unshare_test (void)
> +{
> +  struct support_descriptors *descrs1 = support_descriptors_list ();
> +
> +  /* Check if the temporary file descriptor has no no gaps.  */
> +  int lowfd = open_multiple_temp_files ();
> +
> +  struct support_descriptors *descrs2 = support_descriptors_list ();
> +
> +  enum { stack_size = 4096 };
> +  DEFINE_STACK (stack, stack_size);
> +  pid_t pid = xclone (close_range_unshare_test_fn, (void*) (uintptr_t) lowfd,
> +		      stack, stack_size, CLONE_FILES | SIGCHLD);

Likewise.

Thanks,
Florian


  reply	other threads:[~2021-03-09  9:47 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-23 16:36 [PATCH v3 1/4] support: Add xclone Adhemerval Zanella
2020-12-23 16:36 ` [PATCH v3 2/4] Linux: Add close_range Adhemerval Zanella
2021-03-09  9:47   ` Florian Weimer [this message]
2021-03-09 10:02     ` Christian Brauner
2021-03-09 17:53     ` Adhemerval Zanella
2021-03-09 18:30       ` Florian Weimer
2020-12-23 16:36 ` [PATCH v3 3/4] io: Add closefrom [BZ #10353] Adhemerval Zanella
2021-03-09 10:23   ` Florian Weimer
2021-03-09 19:07     ` Adhemerval Zanella
2020-12-23 16:36 ` [PATCH v3 4/4] posix: Add posix_spawn_file_actions_closefrom Adhemerval Zanella
2021-03-09 10:45   ` Florian Weimer
2021-03-09 19:48     ` Adhemerval Zanella
2021-03-09 20:00       ` Florian Weimer
2021-03-09 20:04         ` Adhemerval Zanella
2021-03-09  9:19 ` [PATCH v3 1/4] support: Add xclone Florian Weimer
2021-03-09 16:17   ` Adhemerval Zanella

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87mtvc64kw.fsf@oldenburg.str.redhat.com \
    --to=fweimer@redhat.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).