-
Notifications
You must be signed in to change notification settings - Fork 161
RFC: are non-forking subshells still worth having? #480
Description
(Please note: below I use the POSIX definition of "subshell", and not any other confused and misleading notion of "subshell" used in various shell manuals and tutorials. To quote: "A subshell environment shall be created as a duplicate of the shell environment, except that signal traps that are not being ignored shall be set to the default action. Changes made to the subshell environment shall not affect the shell environment. Command substitution, commands that are grouped with parentheses, and asynchronous lists shall be executed in a subshell environment. Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment.")
All shells except ksh93 fork off a new process to create a subshell environment. ksh93's non-forking implementation of subshell environments has always been rife with problems. Even David Korn has never managed to create a cleanly separate execution environment without forking a new process.
One egregious issue is #73, which can silently cause the execution of the wrong code. Every ksh93 version has that bug. Other issues include #108 and #416.
#478 is a recent regression related to non-forking subshells. In that issue, @siteshwar inserted a telling comment:
Unfortunately the code to handle input/output in subshells is too complicated and it's very likely that fixing each bug will create another regression.
I cannot but agree. I, for one, am unable to understand the ksh93 source code. It is very convoluted and there are hardly any comments. I have to say I have great respect for @krader1961 and @siteshwar for having taken this on.
Now, as far as I know, there are two original reasons why ksh93 implemented subshells without forking a process:
- Performance: forks used to be expensive.
- To run on systems without fork().
I don't think either of these still apply. Forks have been pretty cheap for a long time now. Even on Windows it's much better than it used to be. There are shells such as dash and FreeBSD sh that are faster than ksh93 while still forking their subshells. And good luck finding a system without fork() younger than 20 years. I assume you're not trying to be compatible with FreeDOS. :)
And of course ksh93 is already perfectly capable of forking off a subshell in a new process: by necessity it does so for a background job. In certain cases it also forks off a command substitution containing a redirection (see my comment on #478). And of course, forked subshells are always cleanly separate because the separation is enforced by the kernel.
Non-forking subshells were an interesting experiment conceived at AT&T that may have served a purpose for a time, but never worked quite right. Now that operating systems have matured, it seems to me that the need for them has gone away.
So here's a radical idea. Why not simply disable and then remove the whole non-forking subshell experiment and fork all subshells like other shells do? I think you'd see a lot of bugs simply disappear, and you'd be removing a maintenance nightmare as well.
What do you think?