Overhaul spawnveg to use clone(2) and fix many related spawning bugs #888
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This commit is a rewrite of #881. The previous pull request didn't address lingering bugs with
E2BIGhandling and file descriptor leaks, proving unsatisfactory. After support for direct usage ofclonewas added tospawnveg, the previous fixes for theposix_spawnimplementation wound up unused and were scrapped (although those changes do work just fine and can be readded if that's desirable).Alterations:
spawnvegthat creates a new process withclone(2)outright. This method is generally faster than usingposix_spawn(3), and is also more portable (because Linux with musl libc and NetBSD both provideclone, but notposix_spawn_file_actions_addtcsetpgrp_np). This code was initially based on the_real_vforkcode previously removed in ef9a5c7 (unlikevfork(2), there is no problem with doing stuff prior toexecveforclonewithCLONE_VM | CLONE_VFORK).tcsetpgrpviaposix_spawn_file_actions_addtcsetpgrp_np(). This code was only ever used with glibc 2.35+. (Not only that, but the only other platform that ever considered implementing a similar function was NetBSD1, where it appears to have been abandoned. This is ironic considering ksh no longer usesposix_spawnon NetBSD as of this commit.) This code may be worth revisiting ifio_uring_spawn()2 is ever actualized (that project appears to be rather inactive though).Demonstration of the (small) performance improvement garnered from using
clonedirectly rather than viaposix_spawn:spawnveg. This is the primary cause of a lockup in the pty tests which can be reproduced as follows:The correct way to go about dealing with
SIGT*is to set those toSIG_DFLin the child process3.tcsetpgrpto theforkfallback inspawnveg. Some form of this appears to have already been attempted in AT&T olden times, but that old version was broken and needed bugfixes desperately.tcsetpgrp, block the terminal signals in the parent process viasigcritical().forkfallback forspawnvegworks correctly in interactive terminals, prefer that to thesh_fork()codepath on operating systems withoutclonesupport. Even though the underlying system call is still ultimatelyfork, thesh_ntforkcodepath is faster than the traditionalsh_forkcodepath. Benchmark:spawnvegimplementations intospawnveg_fastandspawnveg_slow. Choose the appropriate one whenspawnvegis called; this removes the need for the xec.c ifdef hackery.ntfork_tcpgrpifdefs from xec.c;spawnvegcan handle it by itself now.spawnveg_fastandspawnveg_slowinnovation,spawnvegnow always has support forsetsid. It'll fallback tofork()ifPOSIX_SPAWN_SETSIDandclone()aren't available.posix_spawnversion ofspawnveg, the flags should be of the short type pursuant to the POSIX specification.pipe2in theforkfallback forspawnvegwhen it's available to avoid twofcntlsyscalls.spawnvegdocumentation to reflect the new changes._spawnveg(): Restore the terminal process group immediately after any relevant failed spawn attempt, rather than only insh_ntfork().tcsetpgrpplacement.Reproducer that could cause ksh to prematurely exit (for Linux systems with glibc 2.35+):
path_spawn(): Do not print an error message andlongjmpaway upon encounteringE2BIGor some other error; let the calling functions take care of that.path_exec(): Added handling forE2BIG.sh_ntforkto leak file descriptors upon encountering an error (re: 8f848bc). (This bug/regression was encountered after fixing the badtcsetpgrpusage.) Reproducer:commandandcommand -x.sigcritical()nesting matches. The ksh2020 devs appeared to have been confused by this line of code, so some additional clarification explaining what it does should be helpful for posterity.&operator.Footnotes
https://blog.netbsd.org/tnf/entry/gsoc_reports_make_system_31 ↩
https://lwn.net/Articles/908268/ ↩
cf.
_sh_fork()↩