Accessing sys_siglist directly requires rtld to copy it from libc to the sh
executable's BSS. Also, strsignal() will put in the signal number for
unknown signals (FreeBSD-specific) so we need not do that ourselves.
Unfortunately, there is no function for sys_signame.
This reduces code duplication and code size.
/usr/bin/printf is not affected.
Side effect: different error messages when certain builtins are passed
invalid options.
When waiting for child processes using "wait" or if "set -T" is in effect, a
signal interrupts the wait. Make sure there is no window where the signal
handler may be invoked (setting a flag) just before going to sleep.
There is a similar race condition in the shell language, but scripts can
avoid it by exiting from the trap handler or enforcing synchronization using
a fifo.
If SIGCHLD is not trapped, a signal handler must be installed for it. Only
install this handler for the duration of the wait to avoid triggering
unexpected [EINTR] errors elsewhere.
Note that for some reason only SIGINT and SIGQUIT interrupt a "wait"
command. This remains the case.
This uses vfork() for simple commands and command substitutions containing a
single simple command, invoking an external program under certain conditions
(no redirections or variable assignments, non-interactive shell, no job
control). These restrictions limit the amount of code executed in a vforked
child.
There is a large speedup (for example 35%) in microbenchmarks. The
difference in buildkernel is smaller (for example 0.5%) but still
statistically significant. See
http://lists.freebsd.org/pipermail/freebsd-hackers/2012-January/037581.html
for some numbers.
The use of vfork() can be disabled by setting a variable named
SH_DISABLE_VFORK.
Have mkbuiltins write the prototypes for the *cmd functions to builtins.h
instead of builtins.c and include builtins.h in more .c files instead of
duplicating prototypes for *cmd functions in other headers.
In optimized command substitution, save and restore any variables changed by
expansions (${var=value} and $((var=assigned))), instead of trying to
determine if an expansion may cause such changes.
If $! is referenced in optimized command substitution, do not cause jobs to
be remembered longer.
This fixes $(jobs $!) again, simplifies the man page and shortens the code.
These are called "shell procedures" in the source.
If execve() failed with [ENOEXEC], the shell would reinitialize itself
and execute the program as a script. This requires a fair amount of code
which is not frequently used (most scripts have a #! magic number).
Therefore just execute a new instance of sh (_PATH_BSHELL) to run the
script.
When a foreground job exits on a signal, a message is printed to stdout
about this. The buffer was not flushed after this which could result in the
message being written to the wrong file if the next command was a builtin
and had stdout redirected.
Example:
sh -c 'kill -9 $$'; : > foo; echo FOO:; cat foo
Reported by: gcooper
MFC after: 1 week
This allows specifying a %job (which is equivalent to the corresponding
process group).
Additionally, it improves reliability of kill from sh in high-load
situations and ensures "kill" finds the correct utility regardless of PATH,
as required by POSIX (unless the undocumented %builtin mechanism is used).
Side effect: fatal errors (any error other than kill(2) failure) now return
exit status 2 instead of 1. (This is consistent with other sh builtins, but
not in NetBSD.)
Code size increases about 1K on i386.
Obtained from: NetBSD
* Prefer kill(-X) to killpg(X).
* Remove some dead code.
* No additional SIGINT is needed if int_pending() is already true.
No functional change is intended.
The code to translate the internal representation to text did not know about
various additions to the internal representation since the original ash and
therefore wrote binary stuff to the terminal.
The code is used in the jobs command and similar output.
Note that the output is far from complete and mostly serves for recognition
purposes.
If describing the status of a pipeline, write all elements of the pipeline
and show the status of the last process (which would also end up in $?).
Only write one report per job, not one for every process that exits.
To keep some earlier behaviour, if any process started by the shell in a
foreground job terminates because of a signal, write a message about the
signal (at most one message per job, however).
Also, do not write messages about signals in the wait builtin in
non-interactive shells. Only true foreground jobs now write such messages
(for example, "Terminated").
In r208489, I added code to reap zombies when forking new processes, to
limit the amount of zombies. However, this can lead to marking a job as done
or stopped if it consists of multiple processes and the first process ends
very quickly. Fix this by only checking for zombies before forking the first
process of a job and not marking any jobs without processes as done or
stopped.
The getpgid() call will fail if the first process in the job has already
terminated, resulting in output of "-1".
The pgid of a job is always the pid of the first process in the job and
other code already relies on this.
- Use %t to print ptrdiff_t values.
- Cast a ptrdiff_t value explicitly to int for a field width specifier.
While here, sort includes.
Submitted by: Garrett Cooper
Unless $! has been referenced for a particular job or $! still contains that
job's pid, forget about it after it has terminated. If $! has been
referenced, remember the job until the wait builtin has reported its
completion (either with the pid as parameter or without parameters).
In interactive mode, jobs are forgotten after termination has been reported,
which happens before primary prompts and through the jobs builtin. Even
then, though, remember a job if $! has been referenced.
This is similar to what is suggested by POSIX and should fix most memory
leaks (which also tend to cause sh to use more CPU time) with long running
scripts that start background jobs.
Caveats:
* Repeatedly referencing $! without ever doing 'wait', like
while :; do foo & echo started foo: $!; sleep 60; done
will still use a lot of memory and CPU time in the long run.
* The jobs and jobid builtins do not cause a job to be remembered for longer
like expanding $! does.
PR: bin/55346
is enabled.
This already worked if without job control.
In either case, this depends on it that a process that terminates due to
SIGINT exits on it (so not with status 1, or worse, 0).
Example:
sleep 5; echo continued
This does not print "continued" any more if sleep is aborted via ctrl+c.
MFC after: 1 month
This prevents accumulating huge amounts of zombies if a script executes
many background commands but no external commands or subshells.
Note that zombies will not be reaped during long calculations (within
the shell process) or read builtins, but those actions do not create
more zombies.
The terminated background commands will also still be remembered by the
shell.
PR: bin/55346
Reset the exception handler in the child to main's.
This avoids inappropriate double cleanups or shell duplication when the
exception is caught, such as 'fc' and future 'command eval' and 'command .'.
* increase buffer size from 100 to 256 bytes
* remove implied flush from out2str(), in particular this avoids unnecessary
flushing in the middle of a -x tracing line
* rename dprintf() to out2fmt_flush(), make it flush out2 and use this
function in various places where flushing is desired after an error
message
process leader for each job. Now the last specified option for the output
format (-l, -p or -s) wins, previously -s trumped -l.
PR: 99926
Submitted by: Ed Schouten and novel (patches modified by me)
automatically it is possible wait4(2) returns -1 and sets
errno = ECHILD if there were forked children. A user can
set such signal handler e.g. via ``trap "" 20'', see a PR
for the test case. Deal with this case and mark a job as
JOBDONE.
PR: bin/90334
Submitted by: bde
MFC after: 4 weeks
XXX from Tor: "The shell can also go into a similar loop if the child was
killed by signal 127, since the shell would believe the child to have
only stopped (WIFSTOPPED() macro returns nonzero value). Disallowing
signals 127 and 128 will fix that problem." See kern/19402 for details.
PR: bin/66242
Submitted by: tegge
Analysis and testcase by: demon
MFC after: 3 weeks
Only use return value from system call if system call succeeded.
Tested with `make world` and some of my own scripts.
This should be MFCed soon. While /bin/sh is hard to test the fix is
obviously correct and can be assumed not to break something else
(famous last words...).
- Removed dead declarations
- Made objects that should have been declared as static, static.
The changes use STATIC instead of static, following the existing
convention in the rest of the code.
Approved by: schweikh (mentor)
MFC after: 2 weeks
pointers. This fixes two format warnings on 64 bits
archs which are fatal now that WFORMAT=0 has been removed.
It doesn't fully fix the sh(1) build on 64 bits platforms
though, there is still some quad_t issues that need to be
fixed.
Tested on: i386, sparc64