mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Support glibc 2.35's posix_spawn_file_actions_addtcsetpgrp_np(3)
This commit implements support for the glibc 2.35
posix_spawn_file_actions_addtcsetpgrp_np(3) extension[2][3],
updating spawnveg(3) to use the new function for setting the
terminal group. This was done with the intention of improving
performance in interactive shells without reintroducing previous
race conditions[4][5].
[1]: https://sourceware.org/pipermail/libc-alpha/2022-February/136040.html
[2]: https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934
[3]: https://sourceware.org/git/?p=glibc.git;a=commit;h=6289d28d
[4]: https://github.com/ksh93/ksh/issues/79
[5]: https://www.mail-archive.com/ast-developers@research.att.com/msg00717.html
src/cmd/ksh93/sh/path.c:
- Tell spawnveg(3) to set the terminal process group when launching
a child process in an interactive shell.
src/cmd/ksh93/sh/xec.c:
- If posix_spawn_file_actions_addtcsetpgrp_np(3) is available,
allow use of spawnveg(3) (via sh_ntfork()) even with job control
active.
- sh_ntfork(): Reimplement most of the SIGTSTP handling code
removed in commit 66c37202.
src/lib/libast/comp/spawnveg.c,
src/lib/libast/misc/procopen.c,
src/lib/libast/features/sys:
- Add support for posix_spawn_file_actions_addtcsetpgrp_np(3).
- Allow spawnveg to set the terminal process group when pgid == 0.
This was necessary to avoid race conditions when using the new
function.
src/lib/libast/features/lib:
- Detect posix_spawn_file_actions_addtcsetpgrp_np(3).
- Do not detect an OS spawnveg(3). With the API changes to spawnveg
in this pull request ksh probably can't use the OS's spawnveg
function anymore. (That's assuming anything else even provides a
spawnveg function to begin with, which is unlikely.)
src/lib/libast/features/api,
src/cmd/ksh93/include/defs.h:
- Bump libast version (20220101 => 20220201) due to the spawnveg(3)
API change.
src/lib/libast/man/spawnveg.3:
- Document the changes to spawnveg(3) in the corresponding man
page. Currently, it will only use the new tcfd argument if
posix_spawn_file_actions_addtcsetpgrp_np(3) is supported. This
could also be implemented for the fork(2) fallback, but for now
I've avoided changing that since actually using it in the fork
code would likely require a lot of hackery to avoid attempting
tcsetpgrp with vfork (the behavior of tcsetpgrp after vfork is
not portable) and would only benefit systems that don't have
posix_spawn and vfork (I can't recall any off the top of my head
that would fall under that category).
- Updated the man page to account for spawnveg's change in
behavior.
Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
parent
c7a774d9df
commit
0863a8eb29
9 changed files with 101 additions and 35 deletions
|
|
@ -32,12 +32,6 @@
|
|||
|
||||
#include <ast.h>
|
||||
|
||||
#if _lib_spawnveg
|
||||
|
||||
NoN(spawnveg)
|
||||
|
||||
#else
|
||||
|
||||
#if _lib_posix_spawn > 1 /* reports underlying exec() errors */
|
||||
|
||||
#include <spawn.h>
|
||||
|
|
@ -45,20 +39,22 @@ NoN(spawnveg)
|
|||
#include <wait.h>
|
||||
|
||||
pid_t
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd)
|
||||
{
|
||||
int err, flags = 0;
|
||||
pid_t pid;
|
||||
posix_spawnattr_t attr;
|
||||
int err, flags = 0;
|
||||
pid_t pid;
|
||||
posix_spawnattr_t attr;
|
||||
#if _lib_posix_spawn_file_actions_addtcsetpgrp_np
|
||||
posix_spawn_file_actions_t actions;
|
||||
#endif
|
||||
|
||||
if (err = posix_spawnattr_init(&attr))
|
||||
goto nope;
|
||||
#if POSIX_SPAWN_SETSID
|
||||
if (pgid == -1)
|
||||
flags |= POSIX_SPAWN_SETSID;
|
||||
else
|
||||
#endif
|
||||
if (pgid)
|
||||
if (pgid && pgid != -1)
|
||||
flags |= POSIX_SPAWN_SETPGROUP;
|
||||
if (flags && (err = posix_spawnattr_setflags(&attr, flags)))
|
||||
goto bad;
|
||||
|
|
@ -69,13 +65,33 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
if (err = posix_spawnattr_setpgroup(&attr, pgid))
|
||||
goto bad;
|
||||
}
|
||||
#if _lib_posix_spawn_file_actions_addtcsetpgrp_np
|
||||
if (tcfd >= 0)
|
||||
{
|
||||
if (err = posix_spawn_file_actions_init(&actions))
|
||||
goto bad;
|
||||
if (err = posix_spawn_file_actions_addtcsetpgrp_np(&actions, tcfd))
|
||||
goto fail;
|
||||
}
|
||||
if (err = posix_spawn(&pid, path, (tcfd >= 0) ? &actions : NiL, &attr, argv, envv ? envv : environ))
|
||||
#else
|
||||
if (err = posix_spawn(&pid, path, NiL, &attr, argv, envv ? envv : environ))
|
||||
#endif
|
||||
{
|
||||
if ((err != EPERM) || (err = posix_spawn(&pid, path, NiL, NiL, argv, envv ? envv : environ)))
|
||||
goto bad;
|
||||
goto fail;
|
||||
}
|
||||
#if _lib_posix_spawn_file_actions_addtcsetpgrp_np
|
||||
if (tcfd >= 0)
|
||||
posix_spawn_file_actions_destroy(&actions);
|
||||
#endif
|
||||
posix_spawnattr_destroy(&attr);
|
||||
return pid;
|
||||
fail:
|
||||
#if _lib_posix_spawn_file_actions_addtcsetpgrp_np
|
||||
if (tcfd >= 0)
|
||||
posix_spawn_file_actions_destroy(&actions);
|
||||
#endif
|
||||
bad:
|
||||
posix_spawnattr_destroy(&attr);
|
||||
nope:
|
||||
|
|
@ -97,8 +113,9 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
#endif
|
||||
|
||||
pid_t
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd)
|
||||
{
|
||||
NOT_USED(tcfd);
|
||||
#if defined(P_DETACH)
|
||||
return spawnve(pgid ? P_DETACH : P_NOWAIT, path, argv, envv ? envv : environ);
|
||||
#else
|
||||
|
|
@ -117,10 +134,11 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
*/
|
||||
|
||||
pid_t
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd)
|
||||
{
|
||||
struct inheritance inherit;
|
||||
|
||||
NOT_USED(tcfd);
|
||||
inherit.flags = 0;
|
||||
if (pgid)
|
||||
{
|
||||
|
|
@ -154,7 +172,7 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
*/
|
||||
|
||||
pid_t
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
||||
spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid, int tcfd)
|
||||
{
|
||||
#if _lib_fork || _lib_vfork
|
||||
int n;
|
||||
|
|
@ -169,6 +187,7 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
NOT_USED(tcfd);
|
||||
if (!envv)
|
||||
envv = environ;
|
||||
#if _lib_spawnve
|
||||
|
|
@ -214,11 +233,9 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
#if _lib_tcgetpgrp
|
||||
if (m)
|
||||
tcsetpgrp(2, pgid);
|
||||
#else
|
||||
#ifdef TIOCSPGRP
|
||||
#elif defined(TIOCSPGRP)
|
||||
if (m)
|
||||
ioctl(2, TIOCSPGRP, &pgid);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
execve(path, argv, envv);
|
||||
|
|
@ -289,5 +306,3 @@ spawnveg(const char* path, char* const argv[], char* const envv[], pid_t pgid)
|
|||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue