posix: Add terminal control setting support for posix_spawn
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Mon, 14 Jun 2021 17:41:31 +0000 (14:41 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 25 Jan 2022 17:07:53 +0000 (14:07 -0300)
Currently there is no proper way to set the controlling terminal through
posix_spawn in race free manner [1].  This forces shell implementations
to keep using fork+exec when launching background process groups,
even when using posix_spawn yields better performance.

This patch adds a new GNU extension so the creating process can
configure the created process terminal group.  This is done with a new
flag, POSIX_SPAWN_TCSETPGROUP, along with two new attribute functions:
posix_spawnattr_tcsetpgrp_np, and posix_spawnattr_tcgetpgrp_np.
The function sets a new attribute, spawn-tcgroupfd, that references to
the controlling terminal.

The controlling terminal is set after the spawn-pgroup attribute, and
uses the spawn-tcgroupfd along with current creating process group
(so it is composable with POSIX_SPAWN_SETPGROUP).

To create a process and set the controlling terminal, one can use the
following sequence:

    posix_spawnattr_t attr;
    posix_spawnattr_init (&attr);
    posix_spawnattr_setflags (&attr, POSIX_SPAWN_TCSETPGROUP);
    posix_spawnattr_tcsetpgrp_np (&attr, tcfd);

If the idea is also to create a new process groups:

    posix_spawnattr_t attr;
    posix_spawnattr_init (&attr);
    posix_spawnattr_setflags (&attr, POSIX_SPAWN_TCSETPGROUP
     | POSIX_SPAWN_SETPGROUP);
    posix_spawnattr_tcsetpgrp_np (&attr, tcfd);
    posix_spawnattr_setpgroup (&attr, 0);

The controlling terminal file descriptor is ignored if the new flag is
not set.

This interface is slight different than the one provided by QNX [2],
which only provides the POSIX_SPAWN_TCSETPGROUP flag.  The QNX
documentation does not specify how the controlling terminal is obtained
nor how it iteracts with POSIX_SPAWN_SETPGROUP.  Since a glibc
implementation is library based, it is more straightforward and avoid
requires additional file descriptor operations to request the caller
to setup the controlling terminal file descriptor (and it also allows
a bit less error handling by posix_spawn).

Checked on x86_64-linux-gnu and i686-linux-gnu.

[1] https://github.com/ksh93/ksh/issues/79
[2] https://www.qnx.com/developers/docs/7.0.0/index.html#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
46 files changed:
NEWS
include/unistd.h
posix/Makefile
posix/Versions
posix/spawn.h
posix/spawnattr_setflags.c
posix/spawnattr_tcgetpgrp.c [new file with mode: 0644]
posix/spawnattr_tcsetpgrp.c [new file with mode: 0644]
posix/tst-spawn6.c [new file with mode: 0644]
sysdeps/mach/hurd/spawni.c
sysdeps/unix/bsd/tcsetpgrp.c
sysdeps/unix/sysv/linux/aarch64/libc.abilist
sysdeps/unix/sysv/linux/alpha/libc.abilist
sysdeps/unix/sysv/linux/arc/libc.abilist
sysdeps/unix/sysv/linux/arm/be/libc.abilist
sysdeps/unix/sysv/linux/arm/le/libc.abilist
sysdeps/unix/sysv/linux/csky/libc.abilist
sysdeps/unix/sysv/linux/hppa/libc.abilist
sysdeps/unix/sysv/linux/i386/libc.abilist
sysdeps/unix/sysv/linux/ia64/libc.abilist
sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
sysdeps/unix/sysv/linux/microblaze/be/libc.abilist
sysdeps/unix/sysv/linux/microblaze/le/libc.abilist
sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
sysdeps/unix/sysv/linux/nios2/libc.abilist
sysdeps/unix/sysv/linux/or1k/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist
sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
sysdeps/unix/sysv/linux/sh/be/libc.abilist
sysdeps/unix/sysv/linux/sh/le/libc.abilist
sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
sysdeps/unix/sysv/linux/spawni.c
sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
termios/tcsetpgrp.c

diff --git a/NEWS b/NEWS
index 07e9eac52d531afec15297ad546157d98c1c2c20..a9f25d32255d4a0d09796e3610fe4e7fb0dba6a9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -129,6 +129,11 @@ Major new features:
 * On Linux, the epoll_pwait2 function has been added.  It is similar to
   epoll_wait with the difference the timeout has nanoseconds resolution.
 
+* The functions posix_spawnattr_tcsetpgrp_np and posix_spawnattr_tcgetpgrp_np
+  have been added, enabling posix_spawn and posix_spawnp to set the
+  controlling terminal in the new process in a race free manner.  These
+  functions are GNU extensions.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * On x86-64, the LD_PREFER_MAP_32BIT_EXEC environment variable support
index 2bcdd494e1ed54b1338e7607de6bde986a0377b8..7090169601cff3291d24768d0e7d3a50a500bb67 100644 (file)
@@ -183,6 +183,8 @@ extern int __truncate (const char *path, __off_t __length);
 extern void *__sbrk (intptr_t __delta);
 libc_hidden_proto (__sbrk)
 
+extern int __tcsetpgrp (int fd, __pid_t pgrp);
+libc_hidden_proto (__tcsetpgrp)
 
 /* This variable is set nonzero at startup if the process's effective
    IDs differ from its real IDs, or it is otherwise indicated that
index 831759c59f36e8984196f7cc6edac6066b964be6..2b5b79137419b02569b02651b556d6392dd92245 100644 (file)
@@ -64,6 +64,7 @@ routines :=                                                                 \
        spawnattr_getpgroup spawnattr_setpgroup spawn spawnp spawni           \
        spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
        spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
+       spawnattr_tcgetpgrp spawnattr_tcsetpgrp                               \
        posix_madvise                                                         \
        get_child_max sched_cpucount sched_cpualloc sched_cpufree \
        streams-compat \
@@ -108,7 +109,7 @@ tests               := test-errno tstgetopt testfnm runtests runptests \
                   tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
                   bug-regex38 tst-regcomp-truncated tst-spawn-chdir \
                   tst-wordexp-nocmd tst-execveat tst-spawn5 \
-                  tst-sched_getaffinity
+                  tst-sched_getaffinity tst-spawn6
 
 # Test for the glob symbol version that was replaced in glibc 2.27.
 ifeq ($(have-GLIBC_2.26)$(build-shared),yesyes)
@@ -289,6 +290,7 @@ tst-execvpe5-ARGS = -- $(host-test-program-cmd)
 tst-spawn-ARGS = -- $(host-test-program-cmd)
 tst-spawn-static-ARGS = $(tst-spawn-ARGS)
 tst-spawn5-ARGS = -- $(host-test-program-cmd)
+tst-spawn6-ARGS = -- $(host-test-program-cmd)
 tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir
 tst-chmod-ARGS = $(objdir)
 tst-vfork3-ARGS = --test-dir=$(objpfx)
index a78792135fb6a707343088da5d7d133d67a75579..e4f4f649b0f21e852061ece34a82f8dbc39fc9cb 100644 (file)
@@ -156,6 +156,10 @@ libc {
     execveat;
     posix_spawn_file_actions_addclosefrom_np;
   }
+  GLIBC_2.35 {
+    posix_spawnattr_tcgetpgrp_np;
+    posix_spawnattr_tcsetpgrp_np;
+  }
   GLIBC_PRIVATE {
     __libc_fork; __libc_pread; __libc_pwrite;
     __nanosleep_nocancel; __pause_nocancel;
index 58f17d1277aa74d292fd2087bdae7c45fe18be72..77790202509906357c84ebbacbb98883f2495a89 100644 (file)
@@ -34,7 +34,8 @@ typedef struct
   sigset_t __ss;
   struct sched_param __sp;
   int __policy;
-  int __pad[16];
+  int __ctty_fd;
+  int __pad[15];
 } posix_spawnattr_t;
 
 
@@ -59,6 +60,7 @@ typedef struct
 #ifdef __USE_GNU
 # define POSIX_SPAWN_USEVFORK          0x40
 # define POSIX_SPAWN_SETSID            0x80
+# define POSIX_SPAWN_TCSETPGROUP       0x100
 #endif
 
 
@@ -166,6 +168,18 @@ extern int posix_spawnattr_setschedparam (posix_spawnattr_t *__restrict __attr,
                                          __restrict __schedparam)
      __THROW __nonnull ((1, 2));
 
+#ifdef __USE_GNU
+/* Make the spawned process the foreground process group on the terminal
+   associated with FD (which must be a controlling terminal, and still be
+   associated with its session).  */
+extern int posix_spawnattr_tcsetpgrp_np (posix_spawnattr_t *__attr, int fd)
+     __THROW __nonnull ((1));
+
+/* Return the associated terminal FD in the attribute structure.  */
+extern int posix_spawnattr_tcgetpgrp_np (const posix_spawnattr_t *
+                                        __restrict __attr, int *fd)
+     __THROW __nonnull ((1, 2));
+#endif
 
 /* Initialize data structure for file attribute for `spawn' call.  */
 extern int posix_spawn_file_actions_init (posix_spawn_file_actions_t *
index 3e6fe4ef030b20c336cf72a34ff371cf3607068b..603bfcf911c09d9513af1742b27a1a25acb9fb3d 100644 (file)
@@ -26,7 +26,8 @@
                   | POSIX_SPAWN_SETSCHEDPARAM                                \
                   | POSIX_SPAWN_SETSCHEDULER                                 \
                   | POSIX_SPAWN_SETSID                                       \
-                  | POSIX_SPAWN_USEVFORK)
+                  | POSIX_SPAWN_USEVFORK                                     \
+                  | POSIX_SPAWN_TCSETPGROUP)
 
 /* Store flags in the attribute structure.  */
 int
diff --git a/posix/spawnattr_tcgetpgrp.c b/posix/spawnattr_tcgetpgrp.c
new file mode 100644 (file)
index 0000000..8db33e4
--- /dev/null
@@ -0,0 +1,26 @@
+/* Get the controlling terminal option.
+   Copyright (C) 2022 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 <spawn.h>
+
+int
+posix_spawnattr_tcgetpgrp_np (const posix_spawnattr_t *attr, int *fd)
+{
+  *fd = attr->__ctty_fd;
+  return 0;
+}
diff --git a/posix/spawnattr_tcsetpgrp.c b/posix/spawnattr_tcsetpgrp.c
new file mode 100644 (file)
index 0000000..c3b2ea2
--- /dev/null
@@ -0,0 +1,26 @@
+/* Set the controlling terminal option.
+   Copyright (C) 2022 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 <spawn.h>
+
+int
+posix_spawnattr_tcsetpgrp_np (posix_spawnattr_t *attr, int fd)
+{
+  attr->__ctty_fd = fd;
+  return 0;
+}
diff --git a/posix/tst-spawn6.c b/posix/tst-spawn6.c
new file mode 100644 (file)
index 0000000..5f95bd1
--- /dev/null
@@ -0,0 +1,175 @@
+/* Check posix_spawn set controlling terminal extension.
+   Copyright (C) 2022 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 <array_length.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <intprops.h>
+#include <paths.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <sys/wait.h>
+
+static int
+handle_restart (const char *argv1)
+{
+  int fd = xopen (_PATH_TTY, O_RDONLY, 0600);
+
+  /* If process group is not changed (POSIX_SPAWN_SETPGROUP), then check
+     the creating process one, otherwise check against the process group
+     itself.  */
+  pid_t pgrp;
+  if (strcmp (argv1, "setgrpr") != 0)
+    TEST_COMPARE (sscanf (argv1, "%d", &pgrp), 1);
+  else
+    {
+      pgrp = getpgrp ();
+      /* Check if a new process group was actually created.  */
+      pid_t ppid = getppid ();
+      pid_t pgid = getpgid (ppid);
+      TEST_VERIFY (pgid != pgrp);
+    }
+
+  TEST_COMPARE (tcgetpgrp (fd), pgrp);
+
+  xclose (fd);
+  return 0;
+}
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+static void
+run_subprogram (int argc, char *argv[], const posix_spawnattr_t *attr,
+               int exp_err)
+{
+  short int flags;
+  TEST_COMPARE (posix_spawnattr_getflags (attr, &flags), 0);
+  bool setpgrp = flags & POSIX_SPAWN_SETPGROUP;
+
+  char *spargv[9];
+  char pgrp[INT_STRLEN_BOUND (pid_t)];
+
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  if (setpgrp)
+    spargv[i++] = (char *) "setgrpr";
+  else
+    {
+      snprintf (pgrp, sizeof pgrp, "%d", getpgrp ());
+      spargv[i++] = pgrp;
+    }
+  spargv[i] = NULL;
+  TEST_VERIFY_EXIT (i < array_length (spargv));
+
+  pid_t pid;
+  TEST_COMPARE (posix_spawn (&pid, argv[1], NULL, attr, spargv, environ),
+               exp_err);
+  if (exp_err != 0)
+    return;
+
+  int status;
+  TEST_COMPARE (xwaitpid (pid, &status, WUNTRACED), pid);
+  TEST_VERIFY (WIFEXITED (status));
+  TEST_VERIFY (!WIFSTOPPED (status));
+  TEST_VERIFY (!WIFSIGNALED (status));
+  TEST_COMPARE (WEXITSTATUS (status), 0);
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  /* We must have either:
+     - four parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name
+     - six parameters left if called through re-execution:
+       + --setgrpr             optional
+   */
+
+  if (restart)
+    return handle_restart (argv[1]);
+
+  int tcfd = xopen (_PATH_TTY, O_RDONLY, 0600);
+
+  /* Check getters and setters.  */
+  {
+    posix_spawnattr_t attr;
+    TEST_COMPARE (posix_spawnattr_init (&attr), 0);
+    TEST_COMPARE (posix_spawnattr_tcsetpgrp_np (&attr, tcfd), 0);
+
+    int fd;
+    TEST_COMPARE (posix_spawnattr_tcgetpgrp_np (&attr, &fd), 0);
+    TEST_COMPARE (tcfd, fd);
+  }
+
+  /* Check setting the controlling terminal without changing the group.  */
+  {
+    posix_spawnattr_t attr;
+    TEST_COMPARE (posix_spawnattr_init (&attr), 0);
+    TEST_COMPARE (posix_spawnattr_setflags (&attr, POSIX_SPAWN_TCSETPGROUP),
+                 0);
+    TEST_COMPARE (posix_spawnattr_tcsetpgrp_np (&attr, tcfd), 0);
+
+    run_subprogram (argc, argv, &attr, 0);
+  }
+
+  /* Check setting both the controlling terminal and the create a new process
+     group.  */
+  {
+    posix_spawnattr_t attr;
+    TEST_COMPARE (posix_spawnattr_init (&attr), 0);
+    TEST_COMPARE (posix_spawnattr_setflags (&attr, POSIX_SPAWN_TCSETPGROUP
+                                                  | POSIX_SPAWN_SETPGROUP),
+                 0);
+    TEST_COMPARE (posix_spawnattr_setpgroup (&attr, 0), 0);
+    TEST_COMPARE (posix_spawnattr_tcsetpgrp_np (&attr, tcfd), 0);
+
+    run_subprogram (argc, argv, &attr, 0);
+  }
+
+  /* Trying to set the controlling terminal after a setsid incurs in a ENOTTY
+     from tcsetpgrp.  */
+  {
+    posix_spawnattr_t attr;
+    TEST_COMPARE (posix_spawnattr_init (&attr), 0);
+    TEST_COMPARE (posix_spawnattr_setflags (&attr, POSIX_SPAWN_TCSETPGROUP
+                                                  | POSIX_SPAWN_SETSID), 0);
+    TEST_COMPARE (posix_spawnattr_tcsetpgrp_np (&attr, tcfd), 0);
+
+    run_subprogram (argc, argv, &attr, ENOTTY);
+  }
+
+  xclose (tcfd);
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
index ebf2b5e27f97a8c111b03e54f263d9694e120910..bccdd013bf72265d33a5781b0f21ae7640840d25 100644 (file)
@@ -390,6 +390,19 @@ retry:
   if (!err && (flags & POSIX_SPAWN_SETPGROUP) != 0)
     err = __proc_setpgrp (proc, new_pid, attrp->__pgrp);
 
+  /* Set the controlling terminal.  */
+  if (!err && (flags & POSIX_SPAWN_TCSETPGROUP) != 0)
+    {
+      pid_t pgrp;
+      /* Check if it is possible to avoid an extra syscall.  */
+      if ((attrp->__flags & POSIX_SPAWN_SETPGROUP) != 0 && attrp->__pgrp != 0)
+       pgrp = attrp->__pgrp;
+      else
+       err = __proc_getpgrp (proc, new_pid, &pgrp);
+      if (!err)
+        err = __tcsetpgrp (attrp->__ctty_fd, pgrp);
+    }
+
   /* Set the effective user and group IDs.  */
   if (!err && (flags & POSIX_SPAWN_RESETIDS) != 0)
     {
index a7c34ae8d5f9e8b8dcf27808e00e1f872cf22616..272f207c3d0cc166f26ac0bf76a37acb368942a8 100644 (file)
@@ -22,7 +22,9 @@
 
 /* Set the foreground process group ID of FD set PGRP_ID.  */
 int
-tcsetpgrp (int fd, pid_t pgrp_id)
+__tcsetpgrp (int fd, pid_t pgrp_id)
 {
   return __ioctl (fd, TIOCSPGRP, &pgrp_id);
 }
+weak_alias (__tcsetpgrp, tcsetpgrp)
+libc_hidden_def (__tcsetpgrp)
index c1a5ee90e6d4c63e68bfd046048e7d05e9ff386d..9dd574d9e2a7b54139dac39f1569fea220fd0b06 100644 (file)
@@ -2615,3 +2615,5 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 1a30d0666bb76f41da06cb9fc3b6469ee290e794..f66704877eb430529b2c1f91042735fbd7210002 100644 (file)
@@ -2712,6 +2712,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index e5dfdab357c724405c7621ea24982fe67fe5943d..97aa3da1ad15a45960df19eb4d92fb22c90d7a4b 100644 (file)
@@ -2376,3 +2376,5 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 4d3fd872788ba1f03a6b06bb1908e1eef95db13c..18f4364856980df677099fac9f07e1644ca29368 100644 (file)
@@ -495,6 +495,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
index 009dc9da14ee5eed52380b8f7b4d31862e5a660d..2c12c020b1f2f320e40bdbfabc573d58630ef1a1 100644 (file)
@@ -492,6 +492,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
index df8da506cde36eebf527d3a080c6ff9016d042b7..7f28516feb9b3ce0fc4952ef5a29f3e5f305a428 100644 (file)
@@ -2651,3 +2651,5 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 7ea1b017d05cc1fb22b169b14fcfeee52f9c647d..9776f20763a4696318f62cfb06fe705e2b0cd56b 100644 (file)
@@ -2600,6 +2600,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 99ccf354b3d1a762f0b117fd1bd5e34cfeb4e7c9..96b50d0a9bd68a1949afaa3992d64f851435dffc 100644 (file)
@@ -2784,6 +2784,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 201542d1e76daa601396445297feecb8c0df4d63..9b2eebfbf1b91f06bb62dfebe8a91a6bebc6eeab 100644 (file)
@@ -2550,6 +2550,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 32fd72a78df65bd82be2253ecf38b8849145dfa5..71cd35488e3b60abbce3a6ddd05005c366df9092 100644 (file)
@@ -496,6 +496,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
 GLIBC_2.4 _IO_2_1_stdin_ D 0x98
index d26f0ae6c247598406f2593c37d9a8e693a734e7..ced01a501dd816a6b1860e5a8782240f79dce8c5 100644 (file)
@@ -2727,6 +2727,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 520ca0882d8d720b64c0d5a136ecb6c3158c730b..5406c01f1de6280387053edcfd8c5709f3bba062 100644 (file)
@@ -2700,3 +2700,5 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 9162c3139661b2c9972bb6eb762c7563d9e32ecc..53b8ade4c3c16c9fda82dc04ff90ae15f7ea0751 100644 (file)
@@ -2697,3 +2697,5 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 656fdbdcaa70dad61f0555b2f351b45449df3e5a..919973ea46866c8a5d16d02bde6b44207bed8722 100644 (file)
@@ -2692,6 +2692,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 5f0b90d3180306227746b8307ce90534874c0f2b..cf5a8dc1208d1f45d053109125a98e09d722c4d9 100644 (file)
@@ -2690,6 +2690,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 9f4891fc08d7152170a2a660882549e0f0327676..003c3bd0a6bb0595c1384ef93eacd614d092d5a6 100644 (file)
@@ -2698,6 +2698,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index f1b0644bc33ba065bc2e0b6d244a3e2e5c42b9c2..73629c2f21aed4a35323922add2582d95f4fef11 100644 (file)
@@ -2601,6 +2601,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 1cf88e38b943eeb9e666e78cb5db371563b1846c..9e8645ebc0a996a7e1818315a1242429cc041c40 100644 (file)
@@ -2739,3 +2739,5 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index ac2a8284ce31442869b6d1d4729fb9ff5f0041c4..7ed49ee71e475f3d369d1aba99f8bf28fd49a356 100644 (file)
@@ -1395,6 +1395,8 @@ GLIBC_2.35 posix_spawnattr_setschedparam F
 GLIBC_2.35 posix_spawnattr_setschedpolicy F
 GLIBC_2.35 posix_spawnattr_setsigdefault F
 GLIBC_2.35 posix_spawnattr_setsigmask F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.35 posix_spawnp F
 GLIBC_2.35 ppoll F
 GLIBC_2.35 prctl F
index 9692335d106f9400f35b71e867dea0b539412def..3d1ba9887c3278994e74502cd652ec7c3024a673 100644 (file)
@@ -2754,6 +2754,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index 7da0ed59f2ccb080965f33c99b00ac7a3c5d34ea..d979a3b93b98cc5a1c7da73947822eef09678de2 100644 (file)
@@ -2787,6 +2787,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index 72cf6851988a7b91accdc83f6cc4c65860078d60..44688e52cf99e9fcb67e60a4be9225426faab64a 100644 (file)
@@ -2509,6 +2509,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index ee7f67f4d09ba7aef31caee7448c4679728894c7..40682711eb73fb1221ef0f4d010b8f4759e1b52f 100644 (file)
@@ -2811,3 +2811,5 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index b8c0854508ec87144ad90ff89e6f85b85ddd01c5..e239d626b32e03bacd4dbaf5782d51bfbff2068a 100644 (file)
@@ -2378,3 +2378,5 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 90f331fc0bc0627820a21d8da381354631718170..ab0c4e70927d3dc0ee3560927d849f650c6f4254 100644 (file)
@@ -2578,3 +2578,5 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index ded5e3c0ce4da82ca185ed649d4ba1b24da385eb..74e3a4651f21534420ecc925ad2ef5482bcb909c 100644 (file)
@@ -2752,6 +2752,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index 4b262992540d18d691d763f413aa63db9475fd84..e5553f06b205f0cf7c342a26717c548adb2b508e 100644 (file)
@@ -2546,6 +2546,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index 8bfd716fd238a35b09f3552415eacdb090ce0068..9662041cd4c5df836aeebb20e4c487326d34dd19 100644 (file)
@@ -2607,6 +2607,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 47fd204d84ea2432e48fc60d7d4c5f5b53789685..bf90e924a671f1c1a054f10d7903e67f0ff1d8c3 100644 (file)
@@ -2604,6 +2604,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 9b82f15109ca4b1a93b717907622ba3717d22d17..ddb0d0621f80426b85176765f5b14899a77de3e7 100644 (file)
@@ -2747,6 +2747,8 @@ GLIBC_2.35 __epoll_pwait2_time64 F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
index 94caf012a7e9cada759b0d767647c145d4e0c8a8..ca14224cb7d5740d8e6822c94137502f34dd752e 100644 (file)
@@ -2573,6 +2573,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 4c2d4195cd810f998f4089a343f3047cf4b9aa90..93359c708b77dd091cfec3e99c110f287f294df0 100644 (file)
@@ -164,6 +164,17 @@ __spawni_child (void *arguments)
       && __setpgid (0, attr->__pgrp) != 0)
     goto fail;
 
+  /* Set the controlling terminal.  */
+  if ((attr->__flags & POSIX_SPAWN_TCSETPGROUP) != 0)
+    {
+      /* Check if it is possible to avoid an extra syscall.  */
+      pid_t pgrp = (attr->__flags & POSIX_SPAWN_SETPGROUP) != 0
+                   && attr->__pgrp != 0
+                  ? attr->__pgrp : __getpgid (0);
+      if (__tcsetpgrp (attr->__ctty_fd, pgrp) != 0)
+       goto fail;
+    }
+
   /* Set the effective user and group IDs.  */
   if ((attr->__flags & POSIX_SPAWN_RESETIDS) != 0
       && (local_seteuid (__getuid ()) != 0
index 140e9e8c1ce7dd37dfc883bc2305e4d290215779..661d928adf2ac13c9f30a6e971b8f0d78cd79a5b 100644 (file)
@@ -2524,6 +2524,8 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
index 04d13ce27e3747f55b100a09be3f3252b01637f9..bb8058dfa4144bbc102e16f5fd8ed29bad48ad38 100644 (file)
@@ -2630,3 +2630,5 @@ GLIBC_2.34 tss_set F
 GLIBC_2.35 __memcmpeq F
 GLIBC_2.35 _dl_find_object F
 GLIBC_2.35 epoll_pwait2 F
+GLIBC_2.35 posix_spawnattr_tcgetpgrp_np F
+GLIBC_2.35 posix_spawnattr_tcsetpgrp_np F
index 581328b12a44e3d23e86340e4f868b57bbf90cb1..1e4ff0987d3a144f45b641927a884baced5ff5f1 100644 (file)
@@ -21,7 +21,7 @@
 
 /* Set the foreground process group ID of FD set PGRP_ID.  */
 int
-tcsetpgrp (int fd, pid_t pgrp_id)
+__tcsetpgrp (int fd, pid_t pgrp_id)
 {
   if (fd < 0)
     {
@@ -32,6 +32,7 @@ tcsetpgrp (int fd, pid_t pgrp_id)
   __set_errno (ENOSYS);
   return -1;
 }
-
+weak_alias (__tcsetpgrp, tcsetpgrp);
+libc_hidden_def (__tcsetpgrp)
 
 stub_warning (tcsetpgrp)