This represents a "resolved" io_chain_t, where all of the different io_data_t
types have been reduced to a sequence of dup2() and close(). This will
eliminate a lot of the logic duplication around posix_spawn vs fork, and pave
the way for in-process redirections.
By exclusively waiting by pgrp, we can fail to reap processes that
change their own pgrp then either crash or close their fds. If we wind
up in a situation where `waitpid(2)` returns 0 or ECHLD even though we
did not specify `WNOHANG` but we still have unreaped child processes,
wait on them by pid.
Closes#5596.
If we read an R_EOF, we'd try to match mappings to it.
In emacs mode, that's not an issue because the generic binding was
always available, but in vi-normal mode there is no generic binding,
so we'd endlessly loop, waiting for another character.
Fixes#5528.
Originally I sought out to configure the foreground color of the
selected text in the pager. After reading a thread on a github issue I
was inpired to do more: now you can conifgure any part of the pager when
selected, and when a row is secondary. More specifically this commit adds the
ability to specify a pager row's:
- Prefix
- Completion text
- Description
- Background
when said row is selected or secondary.
This will print out along with the stuff we've guessed about color
support. We get a lot of bug reports about these messing up rendering,
this is useful diagnostic output.
Ask the system where utilities are available with confstr (POSIX).
This is the same string printed by `getconf PATH`, which likely
includes more directories.
I was surprised to see:
> set_color normal | string escape
\e\[30m\e\(B\e\[m
I only expected to see a sgr0 here.
Cleanup a nearby `else { if (...) {` and comment with a bogus example.
There was a bogus check for is_interactive_session. But if we are in
reader_readline we are necessarily interactive (even if we are not in
an interactive session, i.e. a fish script invoked some interactive
functionality).
Remove this check.
Fixes#5519
A while loop now evaluates to the last executed command in the body, or
zero if the loop body is empty. This matches POSIX semantics.
Add a bunch of tricky tests.
See #4982
This is effectively a pick of 2ebdcf82ee
and the subsequent fixup. However we also avoid setting WNOHANG unless
waitpid() indicates a process was reaped.
Fixes#5438
For some reason, we have two places where a variable can be read-only:
- By key in env.cpp:is_read_only(), which is checked via set*
- By flag on the actual env_var_t, which is checked e.g. in
parse_execution
The latter didn't happen for non-electric variables like hostname,
because they used the default constructor, because they were
constructed via operator[] (or some such C++-iness).
This caused for-loops to crash on an assert if they used a
non-electric read-only var like $hostname or $SHLVL.
Instead, we explicitly set the flag.
We might want to remove one of the two read-only checks, or something?
Fixes#5548.
Our is_hex_digit() was redundant, we can just use iswxdigit; the libc
implementation is a more efficient table lookup anyhow.
Do is_octal_digit() in terms of iswdigit instead of using wcschr.
This requires threading environment_t through many places, such as completions
and history. We introduce null_environment_t for when the environment isn't
important.
`xlocale.h` is not available on Linux, so we can't just universally
include it.
`HAVE_XLOCALE_H` was already being tested/set in the CMake script as a
possible requirement for `wcstod_l` support, this just adds it to
`config_cmake_h.in` and uses it in `wutil.h` to gate the include.
Removes the dependency on the current user's home directory, instead
overriding it to be within the current hierarchy.
Fixes the tests on Debian buildd, where the home directory is
deliberately unwriteable to pick up errors in builds.
Using `setlocale` is both not thread-safe and not correct, as
a) The global locale is usually stored in static storage, so
simultaneous calls to `setlocale` can result in corruption, and
b) `setlocale` changes the locale for the entire application, not
just the calling thread. This means that even if we wrapped the
`wcstod_l` in a mutex to prevent the previous point, the results
would still be incorrect because this would incorrectly influence the
results of locale-aware functions executed in other threads while
this thread is executing.
The previous comment mentioned that `uselocale` hadn't worked. I'm not
sure what the failing implementation looked like, but `uselocale` can be
tricky. The committed implementation passes the tests for me under Linux
and FreeBSD.
This was the actual issue leading to memory corruption under FreeBSD in
issue #5453, worked around by correcting the detection of `wcstod_l` so
that our version of the function is not called at all.
If we are 100% certain that `wcstod_l` does not exist, then then the
existing code is fine. But given that our checks have failed seperately
on two different platforms already (FreeBSD and Cygwin/newlib), it's a
good precaution to take.
This helps on netbsd, because enter_standout_mode et al are const
there.
These methods don't alter their argument, so they should have been
const to begin with.
This is non-const on macOS, but some of the args we pass are always
const on netbsd.
I have no idea why you'd ever want this to modify its argument, but whatever.
This is the more correct fix for #5447, as regardless of which process
in the job (be it the first or the last) finished first, once we have
waited on a process without ~WNOHANG we don't do that for any subsequent
processes in the job.
It is also a waste to call into the kernel to wait for a process we
already know is completed!
@ridiculousfish had introduced this in 3a45cad12e
to work around an issue with Coverity Scan where it couldn't tell the
mutex was correctly locked, but even with the `fish_mutex_t` hack, it
still emits the same warnings, so there's no pointing in keeping it.
This is necessary for the history race condition test to succeed.
(That test is permanently disabled under WSL (as it always fails) so I
didn't catch this on my end.)
Use `pthread_atfork()` to mark child processes as dirty when `fork()` is
invoked rather than needing to call into the kernel each time
`ASSERT_IS_NOT_FORKED_CHILD()` is called.
This makes simple test cases that hit `ASSERT_IS_NOT_FORKED_CHILD()` 1.8x faster.
------------------------
With a7998c4829 reverted but before this optimization:
```
mqudsi@ZBOOK ~/r/fish-shell> hyperfine -S build/fish 'for i in (seq 100000); test 1 = 1; end'
Benchmark #1: for i in (seq 100000); test 1 = 1; end
Time (mean ± σ): 717.8 ms ± 14.9 ms [User: 503.4 ms, System: 216.2 ms]
Range (min … max): 692.3 ms … 740.2 ms
```
With a7998c4829 reverted and with this optimization:
```
mqudsi@ZBOOK ~/r/fish-shell> hyperfine -S build/fish 'for i in (seq 100000); test 1 = 1; end'
Benchmark #1: for i in (seq 100000); test 1 = 1; end
Time (mean ± σ): 397.2 ms ± 22.3 ms [User: 322.1 ms, System: 79.3 ms]
Range (min … max): 376.0 ms … 444.0 ms
```
Without a7998c4829 reverted and with this optimization:
mqudsi@ZBOOK ~/r/fish-shell> hyperfine -S build/fish 'for i in (seq 100000); test 1 = 1; end'
Benchmark #1: for i in (seq 100000); test 1 = 1; end
Time (mean ± σ): 423.4 ms ± 51.6 ms [User: 363.2 ms, System: 61.3 ms]
Range (min … max): 378.4 ms … 541.1 ms
```
By using a user-land thread-local integer and lock-free (at least under
x86/x64) atomics, we can implement a safe `assert_is_main_thread()`
without calling into the kernel. Thread-local variables are part of
C++11.
This is called a lot in some performance-sensitive areas, so it is worth
optimizing.
This fixes#5438 by having fish block while waiting on a foreground job
via its individual processes by enumerating the procs in reverse order,
such that we hang waiting for the last job in the IO chain to terminate,
rather than the first.
If it's a foreground job, it is related to the currently running exec.
This fixes exec in functions, i.e.
function reload
exec fish
end
would previously always ask about the "function reload" job.
Fixes#5449.
Fixesoh-my-fish/oh-my-fish#664.
Mainly this removes the "TYPE_MASK" macro that just masks off the
higher bits, which I don't think were ever actually used.
Much of this seems like anticipation of future direction, but we're
going somewhere else.
This removes the need to run c-compilation on one file, and allows us
to in future c++-ify this a bit.
There's a lot of bit-fiddling here that is quite unnecessary, better
error-handling would be nice...
So far this removes a few more unused things (because I would have had
to port them), including:
- Functions with ARITY > 3 (even 3 isn't used, but just so we don't
get complacent)
- Variables
- Most functions moved out of the header, because only te_interp is used.
- The te_print function
The function `add_disowned_pgid` adds process *group* ids and not
process ids. It multiplies the value by negative 1 to indicate a wait
on a process group, so the original value must be positive.
If a job is disowned that, for some reason, has a pgid that is special
to waitpid, like 0 (process with pgid of the calling process), -1 (any
process), or our actual pgid, that would lead to us waiting for too
many processes when we later try to reap the disowned processes (to
stop zombies from appearing).
And that means we'd snag away the processes we actually do want to
wait for, which would end with us in a waiting loop.
This is tough to reproduce, the easiest I've found was
fish -ic 'sleep 5 &; disown; set -g __fish_git_prompt_showupstream auto; __fish_git_prompt'
in a git repo.
What we do is to not allow special pgids in the disowned_pids list.
That means we might leave a zombie around (though we probably wait on
0 somewhere), but that's preferable to infinitely looping.
See #5426.
Return STATUS_INVALID_ARGS when failing due to evaluation errors,
so we can tell the difference between an error and falseness.
Add a test for the ERANGE error
The rest of the high-numbered exit codes are not values used by scripts
or builtins, they are internal to fish and come out of
the parser for example.
Prior to adding STATUS_INVALID_ARGS, builtins were usually exiting 2
if they had a special exit status for the situation of bad arguments.
Set it to 2.
We were not parsing an in-range number when we claimed we were,
and were thus failing to error with invalid numbers and returned
a wrong test result. Fixed#5414
Also, provide the detail we can for the other error cases.
Return STATUS_INVALID_ARGS when failing due to evaluation errors,
so we can tell the difference between an error and falseness.
Add a test for the ERANGE error
The rest of the high-numbered exit codes are not values used by scripts
or builtins, they are internal to fish and come out of
the parser for example.
Prior to adding STATUS_INVALID_ARGS, builtins were usually exiting 2
if they had a special exit status for the situation of bad arguments.
Set it to 2.
Cleaned up the code to no longer replicate in fishscript what fish
already does (and caches to boot) in C++ in setting up the paths to the
user configuration directory.
Also introduced a `$__fish_user_data_dir` instead of the sporadic
definitions of `$userdatadir` that may or may not go through
`XDG_DATA_HOME`.
We were not parsing an in-range number when we claimed we were,
and were thus failing to error with invalid numbers and returned
a wrong test result. Fixed#5414
Also, provide the detail we can for the other error cases.
Just sets locale to "C" (because that's the only one we need), does
wcstod and resets the locale.
No idea why uselocale(loc) failed for me, but it did.
Fixes#5407.
This happens in firejail, and it means that we can't use it as an
argument to most pgid-taking functions.
E.g. `wait(0)` means to wait for the _current_ process group,
`tcsetpgrp(0)` doesn't work etc.
So we just stop doing this stuff and hope it works.
Fixes#5295.
This reverts commit 1cb8b2a87b.
argv[0] has the full path in it for a user when he executes it
out of $PATH. This is really annoying in the title which uses $_.
Also check if that is actually defined, not the cur_term proxy.
In #5371, we figured out that there are terminfo entries without this
capability, so this would do a NULL-dereference.
OCLINT was ignoring this, but we can just not do the bad thing.
Declare argc and argv const. These are in the stack, they can
be modified, but we won't.
Fix a typo
... rather than hard code it to "fish". This affects
what is found in $_ and improves the errors:
For example, if fish was ran with ./fish, instead of
something like:
fish: Expected 3 surprises, only got 2 surprises
we'll see:
./fish: Expected 3 surprises, only got 2 surprises
like most other shell utilities. It's just a tiny bit
of detail that can avoid confusion.
This broke fishtape, which did
somestuff | fish -c "source"
Because `source` didn't have a redirection, it refused to read from
stdin.
So, to keep the common issue of `source (command that does not print)`
from seeminly stopping fish, we instead actually check if stdin is a terminal.
This was causing problems if "fish" wasn't in exec_path, like
if the binary had been renamed.
I also noticed that even with 'fish' not renamed, only paths.data
was made relative to my source tree. paths.sysconf, paths.doc, and
paths.bin were all relative to /usr/local.
This had a bunch of "do_{backward,forward}" movements that differed
only in one argument.
Just keep them together, so it's less code, and less needs to be
changed.