public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] hurd: Implement close_range and closefrom
       [not found] <20211106121608.n2cafnwzlbdy5uaw@begin>
@ 2021-11-06 15:35 ` Sergey Bugaev
  2021-11-07 15:17   ` Samuel Thibault
  0 siblings, 1 reply; 3+ messages in thread
From: Sergey Bugaev @ 2021-11-06 15:35 UTC (permalink / raw)
  To: libc-alpha; +Cc: bug-hurd, samuel.thibault, liberamenso10000, Sergey Bugaev

The close_range () function implements the same API as the Linux and
FreeBSD syscalls. It operates atomically and reliably. The specified
upper bound is clamped to the actual size of the file descriptor table;
it is expected that the most common use case is with last = UINT_MAX.

Like in the Linux syscall, it is also possible to pass the
CLOSE_RANGE_CLOEXEC flag to mark the file descriptors in the range
cloexec instead of acually closing them.

Also, add a Hurd version of the closefrom () function. Since unlike on
Linux, close_range () cannot fail due to being unuspported by the
running kernel, a fallback implementation is never necessary.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
 sysdeps/mach/hurd/Makefile          |  1 +
 sysdeps/mach/hurd/Versions          |  3 ++
 sysdeps/mach/hurd/bits/unistd_ext.h | 34 +++++++++++++++
 sysdeps/mach/hurd/close_range.c     | 67 +++++++++++++++++++++++++++++
 sysdeps/mach/hurd/closefrom.c       | 29 +++++++++++++
 sysdeps/mach/hurd/i386/libc.abilist |  1 +
 6 files changed, 135 insertions(+)
 create mode 100644 sysdeps/mach/hurd/bits/unistd_ext.h
 create mode 100644 sysdeps/mach/hurd/close_range.c
 create mode 100644 sysdeps/mach/hurd/closefrom.c

diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
index 17bb643c18..595002bc6a 100644
--- a/sysdeps/mach/hurd/Makefile
+++ b/sysdeps/mach/hurd/Makefile
@@ -197,6 +197,7 @@ endif
 
 ifeq (io, $(subdir))
 sysdep_routines += f_setlk close_nocancel close_nocancel_nostatus \
+		   close_range closefrom \
 		   fcntl_nocancel open_nocancel openat_nocancel read_nocancel \
 		   pread64_nocancel write_nocancel pwrite64_nocancel \
 		   wait4_nocancel \
diff --git a/sysdeps/mach/hurd/Versions b/sysdeps/mach/hurd/Versions
index 89dabd0485..ac38ed44dd 100644
--- a/sysdeps/mach/hurd/Versions
+++ b/sysdeps/mach/hurd/Versions
@@ -10,6 +10,9 @@ libc {
   GLIBC_2.32 {
     mremap;
   }
+  GLIBC_2.34 {
+    close_range;
+  }
   GLIBC_PRIVATE {
     # Functions shared with the dynamic linker
     __access; __access_noerrno; __libc_read; __libc_write; __libc_lseek64;
diff --git a/sysdeps/mach/hurd/bits/unistd_ext.h b/sysdeps/mach/hurd/bits/unistd_ext.h
new file mode 100644
index 0000000000..288f504a3c
--- /dev/null
+++ b/sysdeps/mach/hurd/bits/unistd_ext.h
@@ -0,0 +1,34 @@
+/* System-specific extensions of <unistd.h>, Hurd version.
+   Copyright (C) 2019-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _UNISTD_H
+# error "Never include <bits/unistd_ext.h> directly; use <unistd.h> instead."
+#endif
+
+#ifdef __USE_GNU
+
+/* Set the FD_CLOEXEC bit instead of closing the file descriptor.  */
+#define CLOSE_RANGE_CLOEXEC (1U << 2)
+
+/* Close the file descriptors from FIRST up to LAST, inclusive.
+   If CLOSE_RANGE_CLOEXEC is set in FLAGS, set the FD_CLOEXEC flag
+   instead of closing.  */
+extern int close_range (unsigned int __first, unsigned int __last,
+			int __flags) __THROW;
+
+#endif /* __USE_GNU  */
diff --git a/sysdeps/mach/hurd/close_range.c b/sysdeps/mach/hurd/close_range.c
new file mode 100644
index 0000000000..d6a2eab086
--- /dev/null
+++ b/sysdeps/mach/hurd/close_range.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Close the file descriptors from FIRST up to LAST, inclusive.
+   If CLOSE_RANGE_CLOEXEC is set in FLAGS, set the FD_CLOEXEC flag
+   instead of closing.  */
+int
+__close_range (unsigned int first, unsigned int last,
+               int flags)
+{
+  int i;
+
+  if (first > last)
+    return __hurd_fail (EINVAL);
+  if (flags & ~CLOSE_RANGE_CLOEXEC)
+    return __hurd_fail (EINVAL);
+
+  HURD_CRITICAL_BEGIN;
+  __mutex_lock (&_hurd_dtable_lock);
+
+  for (i = first; i <= last && i < _hurd_dtablesize; i++)
+    {
+      struct hurd_fd *fd = _hurd_dtable[i];
+
+      if (fd == NULL || fd->port.port == MACH_PORT_NULL)
+        continue;
+
+      __spin_lock (&fd->port.lock);
+
+      if (flags & CLOSE_RANGE_CLOEXEC)
+        fd->flags |= FD_CLOEXEC;
+      else
+        {
+          _hurd_port_set (&fd->ctty, MACH_PORT_NULL);
+          _hurd_port_locked_set (&fd->port, MACH_PORT_NULL);
+        }
+
+      __spin_unlock (&fd->port.lock);
+    }
+
+  __mutex_unlock (&_hurd_dtable_lock);
+  HURD_CRITICAL_END;
+
+  return 0;
+}
+
+libc_hidden_def (__close_range)
+strong_alias (__close_range, __libc_close_range)
+weak_alias (__close_range, close_range)
diff --git a/sysdeps/mach/hurd/closefrom.c b/sysdeps/mach/hurd/closefrom.c
new file mode 100644
index 0000000000..5d667cf6c4
--- /dev/null
+++ b/sysdeps/mach/hurd/closefrom.c
@@ -0,0 +1,29 @@
+/* Close a range of file descriptors.  Hurd version.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <sys/param.h>
+
+void
+__closefrom (int lowfd)
+{
+  int l = MAX (0, lowfd);
+
+  (void) __close_range (l, ~0U, 0);
+}
+weak_alias (__closefrom, closefrom)
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index e849d6fa35..729c29f0e1 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2240,6 +2240,7 @@ GLIBC_2.34 _Fork F
 GLIBC_2.34 __isnanf128 F
 GLIBC_2.34 __libc_start_main F
 GLIBC_2.34 _hurd_libc_proc_init F
+GLIBC_2.34 close_range F
 GLIBC_2.34 closefrom F
 GLIBC_2.34 dladdr F
 GLIBC_2.34 dladdr1 F
-- 
2.33.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hurd: Implement close_range and closefrom
  2021-11-06 15:35 ` [PATCH] hurd: Implement close_range and closefrom Sergey Bugaev
@ 2021-11-07 15:17   ` Samuel Thibault
  2021-11-07 18:41     ` Adhemerval Zanella
  0 siblings, 1 reply; 3+ messages in thread
From: Samuel Thibault @ 2021-11-07 15:17 UTC (permalink / raw)
  To: Sergey Bugaev; +Cc: libc-alpha, bug-hurd, liberamenso10000

Hello,

Applied, thanks!

(I have just fixed the symbol version: glibc 2.34 is already out, we are
preparing glibc 2.35).

Samuel

Sergey Bugaev, le sam. 06 nov. 2021 18:35:24 +0300, a ecrit:
> The close_range () function implements the same API as the Linux and
> FreeBSD syscalls. It operates atomically and reliably. The specified
> upper bound is clamped to the actual size of the file descriptor table;
> it is expected that the most common use case is with last = UINT_MAX.
> 
> Like in the Linux syscall, it is also possible to pass the
> CLOSE_RANGE_CLOEXEC flag to mark the file descriptors in the range
> cloexec instead of acually closing them.
> 
> Also, add a Hurd version of the closefrom () function. Since unlike on
> Linux, close_range () cannot fail due to being unuspported by the
> running kernel, a fallback implementation is never necessary.
> 
> Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
> ---
>  sysdeps/mach/hurd/Makefile          |  1 +
>  sysdeps/mach/hurd/Versions          |  3 ++
>  sysdeps/mach/hurd/bits/unistd_ext.h | 34 +++++++++++++++
>  sysdeps/mach/hurd/close_range.c     | 67 +++++++++++++++++++++++++++++
>  sysdeps/mach/hurd/closefrom.c       | 29 +++++++++++++
>  sysdeps/mach/hurd/i386/libc.abilist |  1 +
>  6 files changed, 135 insertions(+)
>  create mode 100644 sysdeps/mach/hurd/bits/unistd_ext.h
>  create mode 100644 sysdeps/mach/hurd/close_range.c
>  create mode 100644 sysdeps/mach/hurd/closefrom.c
> 
> diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
> index 17bb643c18..595002bc6a 100644
> --- a/sysdeps/mach/hurd/Makefile
> +++ b/sysdeps/mach/hurd/Makefile
> @@ -197,6 +197,7 @@ endif
>  
>  ifeq (io, $(subdir))
>  sysdep_routines += f_setlk close_nocancel close_nocancel_nostatus \
> +		   close_range closefrom \
>  		   fcntl_nocancel open_nocancel openat_nocancel read_nocancel \
>  		   pread64_nocancel write_nocancel pwrite64_nocancel \
>  		   wait4_nocancel \
> diff --git a/sysdeps/mach/hurd/Versions b/sysdeps/mach/hurd/Versions
> index 89dabd0485..ac38ed44dd 100644
> --- a/sysdeps/mach/hurd/Versions
> +++ b/sysdeps/mach/hurd/Versions
> @@ -10,6 +10,9 @@ libc {
>    GLIBC_2.32 {
>      mremap;
>    }
> +  GLIBC_2.34 {
> +    close_range;
> +  }
>    GLIBC_PRIVATE {
>      # Functions shared with the dynamic linker
>      __access; __access_noerrno; __libc_read; __libc_write; __libc_lseek64;
> diff --git a/sysdeps/mach/hurd/bits/unistd_ext.h b/sysdeps/mach/hurd/bits/unistd_ext.h
> new file mode 100644
> index 0000000000..288f504a3c
> --- /dev/null
> +++ b/sysdeps/mach/hurd/bits/unistd_ext.h
> @@ -0,0 +1,34 @@
> +/* System-specific extensions of <unistd.h>, Hurd version.
> +   Copyright (C) 2019-2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _UNISTD_H
> +# error "Never include <bits/unistd_ext.h> directly; use <unistd.h> instead."
> +#endif
> +
> +#ifdef __USE_GNU
> +
> +/* Set the FD_CLOEXEC bit instead of closing the file descriptor.  */
> +#define CLOSE_RANGE_CLOEXEC (1U << 2)
> +
> +/* Close the file descriptors from FIRST up to LAST, inclusive.
> +   If CLOSE_RANGE_CLOEXEC is set in FLAGS, set the FD_CLOEXEC flag
> +   instead of closing.  */
> +extern int close_range (unsigned int __first, unsigned int __last,
> +			int __flags) __THROW;
> +
> +#endif /* __USE_GNU  */
> diff --git a/sysdeps/mach/hurd/close_range.c b/sysdeps/mach/hurd/close_range.c
> new file mode 100644
> index 0000000000..d6a2eab086
> --- /dev/null
> +++ b/sysdeps/mach/hurd/close_range.c
> @@ -0,0 +1,67 @@
> +/* Copyright (C) 2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <unistd.h>
> +#include <hurd.h>
> +#include <hurd/fd.h>
> +
> +/* Close the file descriptors from FIRST up to LAST, inclusive.
> +   If CLOSE_RANGE_CLOEXEC is set in FLAGS, set the FD_CLOEXEC flag
> +   instead of closing.  */
> +int
> +__close_range (unsigned int first, unsigned int last,
> +               int flags)
> +{
> +  int i;
> +
> +  if (first > last)
> +    return __hurd_fail (EINVAL);
> +  if (flags & ~CLOSE_RANGE_CLOEXEC)
> +    return __hurd_fail (EINVAL);
> +
> +  HURD_CRITICAL_BEGIN;
> +  __mutex_lock (&_hurd_dtable_lock);
> +
> +  for (i = first; i <= last && i < _hurd_dtablesize; i++)
> +    {
> +      struct hurd_fd *fd = _hurd_dtable[i];
> +
> +      if (fd == NULL || fd->port.port == MACH_PORT_NULL)
> +        continue;
> +
> +      __spin_lock (&fd->port.lock);
> +
> +      if (flags & CLOSE_RANGE_CLOEXEC)
> +        fd->flags |= FD_CLOEXEC;
> +      else
> +        {
> +          _hurd_port_set (&fd->ctty, MACH_PORT_NULL);
> +          _hurd_port_locked_set (&fd->port, MACH_PORT_NULL);
> +        }
> +
> +      __spin_unlock (&fd->port.lock);
> +    }
> +
> +  __mutex_unlock (&_hurd_dtable_lock);
> +  HURD_CRITICAL_END;
> +
> +  return 0;
> +}
> +
> +libc_hidden_def (__close_range)
> +strong_alias (__close_range, __libc_close_range)
> +weak_alias (__close_range, close_range)
> diff --git a/sysdeps/mach/hurd/closefrom.c b/sysdeps/mach/hurd/closefrom.c
> new file mode 100644
> index 0000000000..5d667cf6c4
> --- /dev/null
> +++ b/sysdeps/mach/hurd/closefrom.c
> @@ -0,0 +1,29 @@
> +/* Close a range of file descriptors.  Hurd version.
> +   Copyright (C) 2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <unistd.h>
> +#include <sys/param.h>
> +
> +void
> +__closefrom (int lowfd)
> +{
> +  int l = MAX (0, lowfd);
> +
> +  (void) __close_range (l, ~0U, 0);
> +}
> +weak_alias (__closefrom, closefrom)
> diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
> index e849d6fa35..729c29f0e1 100644
> --- a/sysdeps/mach/hurd/i386/libc.abilist
> +++ b/sysdeps/mach/hurd/i386/libc.abilist
> @@ -2240,6 +2240,7 @@ GLIBC_2.34 _Fork F
>  GLIBC_2.34 __isnanf128 F
>  GLIBC_2.34 __libc_start_main F
>  GLIBC_2.34 _hurd_libc_proc_init F
> +GLIBC_2.34 close_range F
>  GLIBC_2.34 closefrom F
>  GLIBC_2.34 dladdr F
>  GLIBC_2.34 dladdr1 F
> -- 
> 2.33.1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] hurd: Implement close_range and closefrom
  2021-11-07 15:17   ` Samuel Thibault
@ 2021-11-07 18:41     ` Adhemerval Zanella
  0 siblings, 0 replies; 3+ messages in thread
From: Adhemerval Zanella @ 2021-11-07 18:41 UTC (permalink / raw)
  To: Sergey Bugaev, libc-alpha, bug-hurd, liberamenso10000



On 07/11/2021 12:17, Samuel Thibault via Libc-alpha wrote:
> Hello,
> 
> Applied, thanks!
> 
> (I have just fixed the symbol version: glibc 2.34 is already out, we are
> preparing glibc 2.35).

We are trying to avoid it by asking the sender to send a fully working
change (so git-pw can be applied and pushed without modification).

>> diff --git a/sysdeps/mach/hurd/closefrom.c b/sysdeps/mach/hurd/closefrom.c
>> new file mode 100644
>> index 0000000000..5d667cf6c4
>> --- /dev/null
>> +++ b/sysdeps/mach/hurd/closefrom.c
>> @@ -0,0 +1,29 @@
>> +/* Close a range of file descriptors.  Hurd version.
>> +   Copyright (C) 2021 Free Software Foundation, Inc.
>> +   This file is part of the GNU C Library.
>> +
>> +   The GNU C Library is free software; you can redistribute it and/or
>> +   modify it under the terms of the GNU Lesser General Public
>> +   License as published by the Free Software Foundation; either
>> +   version 2.1 of the License, or (at your option) any later version.
>> +
>> +   The GNU C Library is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   Lesser General Public License for more details.
>> +
>> +   You should have received a copy of the GNU Lesser General Public
>> +   License along with the GNU C Library; if not, see
>> +   <https://www.gnu.org/licenses/>.  */
>> +
>> +#include <unistd.h>
>> +#include <sys/param.h>
>> +
>> +void
>> +__closefrom (int lowfd)
>> +{
>> +  int l = MAX (0, lowfd);
>> +
>> +  (void) __close_range (l, ~0U, 0);
>> +}

Since hurd is now also mimicking Linuxism, I think we should move close_range()
to be a default exported symbol (based on default closefrom implementation
that calls __getdtablesize() plus __close_nocancel_nostatus()) and
make closefrom() calls it.  We can refactor __closefrom_fallback() to
be empty static inline for hurd (so it would be optimized away).

I really want to avoid to keep adding system specific implementation that
is just similar to generic code. 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-11-07 18:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20211106121608.n2cafnwzlbdy5uaw@begin>
2021-11-06 15:35 ` [PATCH] hurd: Implement close_range and closefrom Sergey Bugaev
2021-11-07 15:17   ` Samuel Thibault
2021-11-07 18:41     ` Adhemerval Zanella

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).