-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Failure to launch external commands due to race condition in 'posix_spawn' usage #79
Comments
Can't reproduce it here on macOS 10.14.6..
The slightly different test in the Ubuntu bug doesn't fail either. |
Marc Wilson dixit:
Can't reproduce it here on macOS 10.14.6..
According to the reporter, they get a working ksh93 if they
disable posix_spawn configure option so it may be a, very
widespread, bug in GNU libc (Linux/kFreeBSD/Hurd-only, I
presume).
|
I can confirm that disabling |
On macOS, the compiler flags used by the Apple version (which I've incorporated into I can also reproduce this bug on FreeBSD, on which Neither of these two systems use GNU libc, so it seems likely that this is a bug in ksh and not in any C library. Does anyone here have an idea how to fix it? Alternatively, I wonder if there would be any disadvantage to simply removing the use of |
Minimal reproducer for regression test: printf '%s\n' 1 2 3 | while read line; do ls /dev/null; done Normal output:
Bug output:
|
Well, I think the advantage of using
So it would be really nice if someone could figure out how to fix ksh's use of |
A few observations:
If input is redirected, instead of piped, no errors.
The invalid behavior is not 100% consistent.
Running a failing command in a sub-shell works (which is the workaround I
have been using).
Using built-in commands work.
sixt $ cat > /tmp/list
1
2
3
sixt $ while read f; do ls -ld /; done < /tmp/xx
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
sixt $ cat /tmp/list | while read f; do ls -ld /; done
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
/bin/ls: /bin/ls: cannot execute [Exec format error]
/bin/ls: /bin/ls: cannot execute [Exec format error]
sixt $ cat /tmp/list | while read f; do ls -ld /; done
/bin/ls: /bin/ls: cannot execute [Exec format error]
/bin/ls: /bin/ls: cannot execute [Exec format error]
/bin/ls: /bin/ls: cannot execute [Exec format error]
sixt $ ksh -c 'cat /tmp/xx | while read f; do ls -ld /; done'
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
drwxr-xr-x 30 root root 4096 Jul 14 08:08 /
sixt $ cat /tmp/list | while read f; do echo $f /; done
1 /
2 /
3 /
sixt $
Chris (chris.bertin@gmail.com or chris.bertin@protonmail.com)
…On Fri, Jul 17, 2020 at 2:24 PM Anuradha Weeraman ***@***.***> wrote:
There has been a bug report of an exec format error when executing "cat
TODO | while read line; do ls; done".
Ref:
- https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=965072
- https://bugs.launchpad.net/ubuntu/+source/ksh/+bug/1887863
I was able to reproduce this issue on 93u+m 2020-07-14 and it appears to
be an issue at least since 93u+ 2012-08-01.
$ cat TODO
1
2
$ cat TODO | while read line; do ls; done
ls: ls: cannot execute [Exec format error]
ls: ls: cannot execute [Exec format error]
Tagging @chrisbertin <https://github.com/chrisbertin> and @mirabilos
<https://github.com/mirabilos> - reporters of the issue.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#79>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AQKGJUJOFTOVXOBFI6ZRDYDR4C6RPANCNFSM4O65E6KA>
.
|
Is this 2020 bug relevant? att#470 and the original ast ML discussion: |
Thanks @posguy99, yes, that is very relevant indeed. So that is another problem with using The RATIONALE section of the POSIX spec for
|
Pointing out, tho, that if you follow those 2020 bugs all the way through, they lead you back to the performance degradation that was an large part of the original ksh2020 kerfuffle. |
Agreed. That's not going to happen though. |
If # Normal build with posix_spawn
$ ./ksh-posix-spawn -c 'time for ((i=1; i!=10000; i++)); do /usr/bin/true; done'
real 0m02.03s
user 0m01.73s
sys 0m00.36s
# posix_spawn removed with OpenSUSE's patch
$ ./ksh-no-posix-spawn -c 'time for ((i=1; i!=10000; i++)); do /usr/bin/true; done'
real 0m01.85s
user 0m01.60s
sys 0m00.28s
# SHOPT_SPAWN ifdef removed with unifdef(1)
$ ./ksh-no-shopt-spawn -c 'time for ((i=1; i!=10000; i++)); do /usr/bin/true; done'
real 0m03.15s
user 0m02.37s
sys 0m00.89s Relevant
The OpenSUSE patch causes |
@JohnoKing: Sounds good to me, but I am having trouble locating the OpenSUSE patch you are referring to. (Their patches are mostly undocumented and their bug tracker is closed to the public.) The only reference to |
|
Just to be safe and thorough when using vfork, have you all considered vfork's NOTES section and especially the content under Caveats? |
Some notes regarding ksh usage of
|
Right, that all makes sense now, thanks for the explanations. So OpenSUSE's ksh-qemu.patch causes ksh to fall back to using But it also removes another feature test ( ksh/src/lib/libast/sfio/sfhdr.h Lines 438 to 448 in 37a9c34
I don't understand how that is related to posix_spawn , so I'm thinking we should perhaps keep that test. Am I still missing something?
|
The |
@JohnoKing: Thank you for your review of the vfork caveats. Would it be possible to introduce the vfork implementation so one could selectively compile using vfork, posix_spawn, or fork [something like |
That is definitely doable. I imagine the ifdefs would look like this: /* SHOPT_SPAWN is used for spawnveg, which can call
posix_spawn, vfork or fork depending on compile
time options. As a result the posix_spawn ifdef is
SHOPT_POSIX_SPAWN since SHOPT_SPAWN needs to
be defined for any of this to have much effect. */
#if !defined(SHOPT_POSIX_SPAWN)
#undef _lib_posix_spawn
#endif
#if defined(SHOPT_VFORK) && defined(_lib_vfork)
#undef _lib_posix_spawn
#endif
#if defined(SHOPT_FORK) && defined(_lib_fork)
#undef _lib_vfork
#undef _real_vfork
#undef _lib_posix_spawn
#endif
/* On Linux syscall(2) can be used to get the real fork system call.
By default fork is a wrapper that calls clone(2). */
#if defined(SHOPT_REAL_FORK) && defined(__linux__)
#undef _lib_vfork
#undef _real_vfork
#undef _lib_posix_spawn
#undef fork
#include <sys/syscall.h>
#define fork syscall(SYS_fork)
#endif |
I'm not in favour of that. It is now clear that ksh's use of |
Here are some new tests on my Mac laptop. With ksh's racy use of
With ksh's
…and, for reference, the classic
@JohnoKing's Linux tests and my own Mac tests (above) suggest that |
My suggestion with providing possible compiling options to use one of the 3 methods was not based on performance but troubleshooting. So, if not in favor of having a |
@hyenias, yes – disabling That's what Apple has been doing all along for their /bin/ksh, which is how I know this. I found I had to remove |
vfork() is a pre-VM, or, at least pre-COW, semi-kludge and I thought it
would have been retired by now... IMHO...
Chris (chris.bertin@gmail.com or chris.bertin@protonmail.com)
…On Sat, Jul 18, 2020 at 9:00 AM Martijn Dekker ***@***.***> wrote:
@hyenias <https://github.com/hyenias>, yes – disabling SHOPT_SPAWN (by
adding -DSHOPT_SPAWN=0 to the compiler option) will still revert to the
classic fork/exec mechanism, just as it does now. The patch causes the AST
spawnveg() function to use vfork, but disabling SHOPT_SPAWN causes
spawnveg() to not be used at all.
That's what Apple has been doing all along for their /bin/ksh, which is
how I know this. I found I had to remove -DSHOPT_SPAWN=0 as a default
compiler option from cc.darwin in order for vfork to be used.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#79 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AQKGJUO23JAMHYWJYJGFRIDR4HBJDANCNFSM4O65E6KA>
.
|
Well, for ksh, it clearly works more correctly than It's true that POSIX no longer specifies it. But if systems remove |
This is the uname output I get:
I have FreeBSD running on an old Compaq Presario CQ60-211DX (which runs a single core Intel Celeron) and in a virtual machine running under VirtualBox, with two CPU cores given to the vm (VirtualBox is running on a desktop with an AMD Ryzen 2600 overclocked to 4.05GHz on all six cores, SMT is enabled). |
Update: After letting it run for a long time, I was able to reproduce the race condition on FreeBSD. It occurred in one out of 1413150 output lines. |
@JohnoKing, first a question: I've sent you a test email, did you receive it? I think there may be a delivery problem. Second, something occurred to me. The original bug report above is only reproducible on an interactive shell. So I decided to test for the testprocessgroup.c race condition on FreeBSD from a script. And I can't reproduce it. Can you confirm the race condition cannot be reproduced if the test loop is run from a script? If so, that opens the door to a workaround: make both the |
I did receive the email. I also sent a reply.
I can confirm that the race condition is not reproducible in scripts with either |
More specifically, the culprit turns out to be job control (the Conversely, if you |
So, after this slightly desperate megathread, could the fix really be this trivial? Please test… diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
index 4f99919..0991406 100644
--- a/src/cmd/ksh93/sh/xec.c
+++ b/src/cmd/ksh93/sh/xec.c
@@ -1587,7 +1587,7 @@ int sh_exec(register const Shnode_t *t, int flags)
#else
#if SHOPT_SPAWN
# ifdef _lib_fork
- if(com)
+ if(com && !job.jobcontrol)
parent = sh_ntfork(shp,t,com,&jobid,ntflag);
else
parent = sh_fork(shp,type,&jobid); |
That patch is an effective fix for the race conditions, at least from my own testing. |
I think it makes sense now. If job control is not active, the terminal process group ID never needs to be set; child processes simply inherit the terminal group from the parent. However, with job control active, each child process spawned from the main shell environment (not subshells) needs to be in its own terminal process group, or you can't separate the jobs from each other. But you can't do this with So it's clear that this What I don't understand is why it doesn't fail consistently. |
This is brilliant, @McDutchie @JohnoKing et al. Thanks for your persistence! @chrisbertin and @mirabilos - this will be included in the next upload fairly shortly. |
@aweeraman, hold off a little – this fix exposes a variant of #86 that only occurs with job control active. I'm working out a good way to fix it. |
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 creating 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 it only provides the POSIX_SPAWN_TCSETPGROUP flag. The QNX documentation is not on how the controlling terminal is obtained not how it iteracts with POSIX_SPAWN_SETPGROUP. Since a glibc implementation is library based, I moving the controlling terminal open to the caller should be more straighforward since it mimics the tcsetpgrp(), and allow less error handling by posix_spawn(). Checked on x86_64-linux-gnu and i686-linux-gnu. [1] ksh93/ksh#79 [2] https://www.qnx.com/developers/docs/7.0.0/index.html#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html
macOS Monterey is apparently deprecating vfork() in favor of posix_spawn()? https://bugs.openjdk.java.net/browse/JDK-8274293 https://www.reddit.com/r/emacs/comments/qp2sxf/anyone_with_macos_monterey_on_an_m1/ |
Thanks @posguy99, vfork() has been deprecated for a long time on some other systems, but it doesn't matter as ksh already uses posix_spawn() in preference to vfork(), so vfork() is only used as a fallback for old systems where posix_spawn() is not available. |
I'll note that there is currently a patch that adds a If that patch gets merged into glibc's upstream codebase then perhaps we could use that flag to safely avoid usage of fork() in interactive shells. |
I just merge this patch [1] and it will be included on glibc 2.35. [1] https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934a3bf74ac618e2318d738f22ac93257ba |
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] ksh93/ksh#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>
Note that this is still a WIP. Current TODOs: - Error out if posix_spawnattr_tcsetpgrp_np is detected but posix_spawn is not. - Document the changes to spawnveg in the relevant man page. - Maybe: Use tcsetpgrp in the spawnveg fork fallback (if this is implemented, vfork will not be allowed to use that function since the behavior of tcsetpgrp after vfork is unpredictable and not portable). This commit implements support for the glibc POSIX_SPAWN_TCSETPGROUP and posix_spawnattr_tcsetpgrp_np extension [1]. This was done with the intention of improving performance in interactive shells without reintroducing previous race conditions[2][3]. These changes were tested with glibc commit 342cc934. src/cmd/ksh93/sh/path.c: - Tell spawnveg to set the terminal process group when launching a child process in an interactive shell. src/cmd/ksh93/sh/xec.c: - Allow posix_spawn when posix_spawnattr_tcsetpgrp_np is available. - Reimplement most of the sh_ntfork() SIGTSTP handling code removed in commit 66c3720. src/lib/libast/comp/spawnveg.c, src/lib/libast/misc/procopen.c, src/lib/libast/features/sys: - Add support for POSIX_SPAWN_TCSETPGROUP as implemented in glibc. This code (with a few changes) might also work on QNX, but I've avoided changing anything on that OS since I don't have a QNX system to test with. - Bugfix 1: If pgid == -1, use POSIX_SPAWN_SETSID when it's available (spawnveg uses setsid(2) after fork/vfork, so it should do the same thing when posix_spawn is used instead. src/lib/libast/features/lib: - Bugfix 2: Fix syntax errors in the posix_spawn feature test that caused ksh to fall back to vfork instead. - Detect the existence of posix_spawnattr_tcsetpgrp_np(). [1]: https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934a3bf74ac618e2318d738f22ac93257ba [2]: ksh93#79 [3]: https://www.mail-archive.com/ast-developers@research.att.com/msg00717.html
This commit implements support for the glibc POSIX_SPAWN_TCSETPGROUP and posix_spawnattr_tcsetpgrp_np extension [1]. This was done with the intention of improving performance in interactive shells without reintroducing previous race conditions[2][3]. These changes were tested with glibc commit 342cc934. src/cmd/ksh93/sh/path.c: - Tell spawnveg to set the terminal process group when launching a child process in an interactive shell. src/cmd/ksh93/sh/xec.c: - Allow usage of spawnveg when posix_spawnattr_tcsetpgrp_np is available. - Reimplement most of the sh_ntfork() SIGTSTP handling code removed in commit 66c3720. src/lib/libast/comp/spawnveg.c, src/lib/libast/misc/procopen.c, src/lib/libast/features/sys: - Add support for POSIX_SPAWN_TCSETPGROUP as implemented in glibc. This code (with a few changes) might also work on QNX, but I've avoided changing anything on that OS since I don't have a QNX system to test with. - Bugfix 1: If pgid == -1, use POSIX_SPAWN_SETSID when it's available (spawnveg uses setsid(2) after fork/vfork, so it should do the same thing when posix_spawn is used instead. src/lib/libast/man/spawnveg.3: - Document the changes to spawnveg(3) in the corresponding man page. Currently spawnveg will only use the new tcfd argument if posix_spawnattr_tcsetpgrp_np is supported. This could also be implemented for the fork 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). src/lib/libast/features/lib: - Bugfix 2: Fix syntax errors in the posix_spawn feature test that caused ksh to fall back to vfork instead. - Detect the existence of the GNU posix_spawnattr_tcsetpgrp_np() extension. [1]: https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934a3bf74ac618e2318d738f22ac93257ba [2]: ksh93#79 [3]: https://www.mail-archive.com/ast-developers@research.att.com/msg00717.html
This commit implements support for the glibc POSIX_SPAWN_TCSETPGROUP and posix_spawnattr_tcsetpgrp_np extensions[1]. This was done with the intention of improving performance in interactive shells without reintroducing previous race conditions[2][3]. These changes were tested with glibc commit 342cc934. src/cmd/ksh93/sh/path.c: - Tell spawnveg to set the terminal process group when launching a child process in an interactive shell. src/cmd/ksh93/sh/xec.c: - Allow usage of spawnveg when posix_spawnattr_tcsetpgrp_np is available. - Reimplement most of the sh_ntfork() SIGTSTP handling code removed in commit 66c3720. src/lib/libast/comp/spawnveg.c, src/lib/libast/misc/procopen.c, src/lib/libast/features/sys: - Add support for POSIX_SPAWN_TCSETPGROUP as implemented in glibc. This code (with a few changes) might also work on QNX, but I've avoided changing anything on that OS since I don't have a QNX system to test with. - Bugfix 1: If pgid == -1, use POSIX_SPAWN_SETSID when it's available (spawnveg uses setsid(2) after fork/vfork, so it should do the same thing when posix_spawn is used instead. src/lib/libast/man/spawnveg.3: - Document the changes to spawnveg(3) in the corresponding man page. Currently spawnveg will only use the new tcfd argument if posix_spawnattr_tcsetpgrp_np is supported. This could also be implemented for the fork 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). src/lib/libast/features/lib: - Bugfix 2: Fix syntax errors in the posix_spawn feature test that caused ksh to fall back to vfork instead. - Detect the existence of the GNU posix_spawnattr_tcsetpgrp_np() extension. [1]: https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934a3bf74ac618e2318d738f22ac93257ba [2]: ksh93#79 [3]: https://www.mail-archive.com/ast-developers@research.att.com/msg00717.html
This commit implements support for the glibc POSIX_SPAWN_TCSETPGROUP and posix_spawnattr_tcsetpgrp_np extensions[1]. This was done with the intention of improving performance in interactive shells without reintroducing previous race conditions[2][3]. These changes were tested with glibc commit 342cc934. src/cmd/ksh93/sh/path.c: - Tell spawnveg to set the terminal process group when launching a child process in an interactive shell. src/cmd/ksh93/sh/xec.c: - Allow usage of spawnveg when posix_spawnattr_tcsetpgrp_np is available. - Reimplement most of the sh_ntfork() SIGTSTP handling code removed in commit 66c3720. src/lib/libast/comp/spawnveg.c, src/lib/libast/misc/procopen.c, src/lib/libast/features/sys: - Add support for POSIX_SPAWN_TCSETPGROUP as implemented in glibc. This code (with a few changes) might also work on QNX, but I've avoided changing anything on that OS since I don't have a QNX system to test with. - Bugfix 1: If pgid == -1, use POSIX_SPAWN_SETSID when it's available (spawnveg uses setsid(2) after fork/vfork, so it should do the same thing when posix_spawn is used instead). src/lib/libast/man/spawnveg.3: - Document the changes to spawnveg(3) in the corresponding man page. Currently spawnveg will only use the new tcfd argument if posix_spawnattr_tcsetpgrp_np is supported. This could also be implemented for the fork 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). src/lib/libast/features/lib: - Bugfix 2: Fix syntax errors in the posix_spawn feature test that caused ksh to fall back to vfork instead. - Detect the existence of the GNU posix_spawnattr_tcsetpgrp_np() extension. [1]: https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934a3bf74ac618e2318d738f22ac93257ba [2]: ksh93#79 [3]: https://www.mail-archive.com/ast-developers@research.att.com/msg00717.html
This commit implements support for the glibc POSIX_SPAWN_TCSETPGROUP and posix_spawnattr_tcsetpgrp_np extensions[1]. This was done with the intention of improving performance in interactive shells without reintroducing previous race conditions[2][3]. These changes were tested with glibc commit 342cc934. [1]: https://sourceware.org/git/?p=glibc.git;a=commit;h=342cc934a3bf74ac618e2318d738f22ac93257ba [2]: #79 [3]: https://www.mail-archive.com/ast-developers@research.att.com/msg00717.html src/cmd/ksh93/sh/path.c: - Tell spawnveg to set the terminal process group when launching a child process in an interactive shell. src/cmd/ksh93/sh/xec.c: - Allow usage of spawnveg when posix_spawnattr_tcsetpgrp_np is available. - Reimplement most of the sh_ntfork() SIGTSTP handling code removed in commit 66c3720. src/lib/libast/comp/spawnveg.c, src/lib/libast/misc/procopen.c, src/lib/libast/features/sys: - Add support for POSIX_SPAWN_TCSETPGROUP as implemented in glibc. This code (with a few changes) might also work on QNX, but I've avoided changing anything on that OS since I don't have a QNX system to test with. src/lib/libast/man/spawnveg.3: - Document the changes to spawnveg(3) in the corresponding man page. Currently spawnveg will only use the new tcfd argument if posix_spawnattr_tcsetpgrp_np is supported. This could also be implemented for the fork 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). src/lib/libast/features/lib: - Detect the existence of the GNU posix_spawnattr_tcsetpgrp_np() extension. - 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.
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]: #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 66c3720. 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>
There has been a bug report of an exec format error when executing "cat TODO | while read line; do ls; done".
Ref:
I was able to reproduce this issue on 93u+m 2020-07-14 and it appears to be an issue at least since 93u+ 2012-08-01.
Tagging @chrisbertin and @mirabilos - reporters of the issue.
The text was updated successfully, but these errors were encountered: