Re: nofork command substitution
Chet Ramey writes: > Bash allows the close brace to be joined to the remaining > characters in the word without being followed by a shell metacharacter > as a reserved word would usually require. I had to read this a couple of times to figure out what it means. In particular "the word" isn't well-bound here. Perhaps better is > The characters immediately following the close brace continue the word > that the command substitution is part of; the close brace need not be > followed by a shell metacharacter as a reserved word would usually > require. This text is clear in its description of the behavior but entirely unclear regarding what the point is: > If the first character is a '|', the construct expands to the value of > the 'REPLY' shell variable after COMMAND executes, without removing any > trailing newlines, and the standard output of COMMAND remains the same > as in the calling shell. Bash creates 'REPLY' as an initially-unset > local variable when COMMAND executes, and restores 'REPLY' to the value > it had before the command substitution after COMMAND completes, as with > any local variable. My guess is that the intention is for COMMAND to be "read" with no names: ${| read; } If so, can you make this an example for the "${|" form? Also, can you clarify the semantics on this point: The text above says "the construct expands to the value of the 'REPLY' shell variable after COMMAND executes, without removing any trailing newlines". However, the documentation of "read" says: "If no names are supplied, the line read, without the ending delimiter but otherwise unmodified, is assigned to the variable REPLY." So the sequence of processing is: read inputs a line; read deletes the ending newline and assigns the remainder to REPLY; command substitution obtains the value of REPLY (which does not contain a newline); command substitution returns that value "without removing any trailing newlines". Is that what you intend the code to do/what the code does? Dale
Re: nofork command substitution
Ãngel writes: > I suggest: > >> There is an alternate form of command substitution: >> >> ${ COMMAND; } > > and clarify later the other variants in addition to a space: > >> The character following the open brace must be a space, tab, >> newline, '(', or '|', and the close brace must be in a position... I support either that change, or reordering the text to specify "C" at the beginning, when the syntax is being described, before the semantics are described: > There is an alternate form of command substitution: > > ${C COMMAND; } > > where the character C following the open brace is a space, tab, newline, > '(', or '|'. This form executes COMMAND in the current execution > environment. This means that side effects of COMMAND take effect > immediately in the current execution environment and persist in the > current environment after the command completes (e.g., the 'exit' > builtin will exit the shell). > > The close brace must be in a position where a > reserved word may appear (i.e., preceded by a command terminator such as > semicolon). ... Dale
Re: `wait -n` returns 127 when it shouldn't
On 5/18/23 7:51 AM, Robert Elz wrote: Apparently, in bash, if the code is running in a (shell) loop (like inside a while, or similar, loop) then each iteration around the loop, any jobs that have exited, but not been cleaned already, are removed from the queue (the jobs table in practice, though bash may also have something else). That's really broken, and should be fixed (but has apparently been that way for decades, and no-one noticed). This isn't a problem, and is a red herring. The code that manages that list makes sure to keep as many jobs in the list as POSIX requires, subject to the maxchild resource limit. In the script in question, the offending loop isn't the one in the main program - in that for each iteration the background processes are started, and waited for, in each iteration, but the one in the waitjobs function. which (appears at first glance, which is all the analysis shells ever do) to be an infinite loop, so each time around, if there are any completed jobs in the table, they're removed. No, this isn't what happens. The problem is that the shell reaps both jobs, but the `wait -n' code had a race condition that prevented it from finding a job in the list. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: `wait -n` returns 127 when it shouldn't
On 5/18/23 12:16 AM, Martin D Kealey wrote: If there is silent reaping going on (other than “wait -n” or “trap ... SIGCHLD”) shouldn't the exit status and pid of each silently reaped process be retained in a queue that “wait -n“ can extract from, in order to maintain the reasonable expected semantics? Arguably this queue should be shared with “fg” when job control is enabled. There is always `silent reaping' going on. This is a red herring. The problem was a race condition in the `wait -n' code. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: `wait -n` returns 127 when it shouldn't
Date:Thu, 18 May 2023 07:35:35 -0400 From:Greg Wooledge Message-ID: | I'm fairly sure most (or all?) shells do this, not just bash. Interactive shells are "different" from those running a script in this regard. kre
Re: `wait -n` returns 127 when it shouldn't
Date:Thu, 18 May 2023 14:16:17 +1000 From:Martin D Kealey Message-ID: | I know that some platforms (used to?) lack all of the âwaitpid()â, This is irrelevant to the issue at hand (and in general, for shells, is irrelevant anyway, as shells usually always clean up the process table as soon as possible, always waiting for anything. Lack of anything more than simple wait() can be problematic, as that hangs, which isn't always desired, but in combination with SIGCHLD (as abominable as that signal is defined to work on some systems) can be made to function. But not relevant here, the script is just doing wait -n (no specific pid requested) and hence there's no need for anything fancy in terms of wait sys called. | If there is silent reaping going on (other than âwait -nâ or âtrap ... | SIGCHLDâ) In practice, there always is, in all shells. | shouldn't the exit status and pid of each silently reaped process | be retained in a queue that âwait -nâ can extract from, Yes, that is what is supposed to happen. And does. The question is when jobs are removed from that queue. | Would you care to speculate more precisely on where such silent reaping may | occur, given the code as shown? Apparently, in bash, if the code is running in a (shell) loop (like inside a while, or similar, loop) then each iteration around the loop, any jobs that have exited, but not been cleaned already, are removed from the queue (the jobs table in practice, though bash may also have something else). That's really broken, and should be fixed (but has apparently been that way for decades, and no-one noticed). The intent is to avoid the queue growing infinitely big in the case of loops like while :; do process& maybe other code but not doing wait; done Note this does not need to be a very speedy loop, just one that runs forever, and never cleans anything up. That's broken, but in old shell scripts, hard to avoid, as the only cleanup method was a simple "wait" which would wait until all background processes completed, defeating the purpose. In the script in question, the offending loop isn't the one in the main program - in that for each iteration the background processes are started, and waited for, in each iteration, but the one in the waitjobs function. which (appears at first glance, which is all the analysis shells ever do) to be an infinite loop, so each time around, if there are any completed jobs in the table, they're removed. Then, if nothing is still running, wait -n returns 127, and we exit. If we're lucky, we get to the wait -n before the false job finishes, and wait -n collects that one (what happens to the background true is completely irrelevant to this script), and everything iterates. If we're unlucky, false has already completed, and its status is lost, before we get a chance to wait for it. Simply broken. What bash should be doing is limiting the number of jobs that can be in the jobs table (to perhaps a few hundred) - deleting the oldest completed ones if more jobs need to be added. That's allowed, solves the infinite new job problem, and allows sane programs that do wait for their children to avoid this kind of issue. | PS: I'm not convinced that âtrap ... SIGCHLDâ needs to be in that list; No, shell level SIGCHLD traps are irrelevant.The semantics of SIGCHLD means that they can't rationally be mapped directly from SIGCHLD signals, those things are hopeless and need to be handled specially by the shell (or always kept at SIG_DFL so they never occur) or things fail badly. kre
Re: `wait -n` returns 127 when it shouldn't
On Thu, May 18, 2023 at 02:16:17PM +1000, Martin D Kealey wrote: > If there is silent reaping going on (other than “wait -n” or “trap ... > SIGCHLD”) [...] Yes, bash silently reaps child processes. unicorn:~$ tty /dev/pts/2 unicorn:~$ sleep 5 & sleep 7 & [1] 942813 [2] 942814 unicorn:~$ tty /dev/pts/0 unicorn:~$ ps -ft pts/2 UID PIDPPID C STIME TTY TIME CMD greg 973 959 0 Apr29 pts/200:00:00 bash greg 942813 973 0 07:29 pts/200:00:00 sleep 5 greg 942814 973 0 07:29 pts/200:00:00 sleep 7 unicorn:~$ ps -ft pts/2 UID PIDPPID C STIME TTY TIME CMD greg 973 959 0 Apr29 pts/200:00:00 bash I didn't touch pts/2 at all during this time. I just ran the ps commands on pts/0. As you can see, the two sleep processes are just *gone*. They are not hanging around as zombies waiting for me to do something on pts/2. At no point did I ever call "wait" explicitly. I'm fairly sure most (or all?) shells do this, not just bash.