As it turns out, NetBSD's rand(3) is awful - it's possible that in any
given run it'll only return odd numbers, which means
while (rand() % 10)
will never stop.
Since random(3) is also standardized and works, let's use that!
Now that we use an internal process to perform builtin output, simplify the
logic around how it is performed. In particular we no longer have to be
careful about async-safe functions since we do not fork.
Also fix a bunch of comments that no longer apply.
This uses the new internal process mechanism to write output for builtins.
After this the only reason fish ever forks is to execute external processes.
This introduces "internal processes" which are backed by a pthread instead
of a normal process. Internal processes are reaped using the topic
machinery, plugging in neatly alongside the sigchld topic; this means that
process_mark_finished_children() can wait for internal and external
processes simultaneously.
Initially internal processes replace the forked process that fish uses to
write out the output of blocks and functions.
This adds an "in-process" interpretation of dup2s, allowing for fish to
output directly to the correct file descriptor without having to perform
an in-kernel dup2 sequence.
The sigchld generation expresses the idea that, if we receive a sigchld
signal, the generation will be different than when we last recorded it. A
process cannot exit before it has launched, so check the generation count
before process launch. This is an optimization that reduces failing
waitpid calls.
This is a big change to how process reaping works, reimplenting it using
topics. The idea is to simplify the logic in
process_mark_finished_children around blocking, and also prepare for
"internal processes" which do not correspond to real processes.
Before this change, fish would use waitpid() to wait for a process group,
OR would individually poll processes if the process group leader was
unreapable.
After this change, fish no longer ever calls blocking waitpid(). Instead
fish uses the topic mechanism. For each reapable process, fish checks if
it has received a SIGCHLD since last poll; if not it waits until the next
SIGCHLD, and then polls them all.
topic_monitor allows for querying changes posted to one or more topics,
initially sigchld. This will eventually replace the waitpid logic in
process_mark_finished_children().
Comment from the new header:
Topic monitoring support. Topics are conceptually "a thing that can
happen." For example, delivery of a SIGINT, a child process exits, etc. It
is possible to post to a topic, which means that that thing happened.
Associated with each topic is a current generation, which is a 64 bit
value. When you query a topic, you get back a generation. If on the next
query the generation has increased, then it indicates someone posted to
the topic.
For example, if you are monitoring a child process, you can query the
sigchld topic. If it has increased since your last query, it is possible
that your child process has exited.
Topic postings may be coalesced. That is there may be two posts to a given
topic, yet the generation only increases by 1. The only guarantee is that
after a topic post, the current generation value is larger than any value
previously queried.
Tying this all together is the topic_monitor_t. This provides the current
topic generations, and also provides the ability to perform a blocking
wait for any topic to change in a particular topic set. This is the real
power of topics: you can wait for a sigchld signal OR a thread exit.
This resolves the issue where running pre-compiled Linux packages from
binary package manager repositories lead fish to think that we are not
running under WSL.
- Closes#5619.
- Ping neovim/neovim#7330
This happens on OpenIndiana/Solaris/Illumos/SunOS.
Elsewhere we use read_blocked, which already returned in this
case (and which we might want to use here as well!).
`fish_title` as invoked by fish itself is not running in an interactive
context, and attempts to read from the input fd (e.g. via `read`) cause
fish to segfault, go into an infinite loop, or hang at the read prompt
depending on the exact command line and fish version.
This patch addresses that by explicitly closing the input fd when
invoking `fish_title`.
Reported by @floam in #5629. May close that issue, but situation is
unclear.
Taking advantage of the maybe_t's, the logic and nesting here
can be a bit less intense.
Small adjustments to debug output, and found a more accurate
version number for Lion Terminal.app.
Longer term we should have a terminal_t class or something
encapsulating all the kinds of terminal detection we have
with methods that return the color support, and also stuff
like whether the terminal has the newline glitch, the
ambiguous width character behavior, etc.
fish forks child processes when (for example) writing out builtin output.
After fork it resets signal handlers, but if a signal is delivered before
the signal handlers are reset, it will inherit fish's default handlers,
which do things like swallow SIGINT. Teach fish's default signal handlers
to detect this case and re-raise signals with default handlers.
This improves the reliability of control-C in the face of builtins.
I hope this is now complete.
Also, shorten enough descriptions to make `string match --<TAB>`
show a two column pager with 80 cols.
We really should have shown more retraint in the design of `string`,
not all of the flags required both a long and short option created.
300ms was waaay too long, and even 100ms wasn't necessary.
Emacs' evil mode uses 10ms (0.01s), so let's stay a tad higher in case
some terminals are slow.
If anyone really wants to be able to type alt+h with escape, let them
raise the timeout.
Fixes#3904.
`/tmp` isn't present / writeable on every system. Instead of always
using `/tmp`, try to use standard environment variables and
configuration to find a temporary directory.
Adapted from #3974, with updates based on those comments.
Closes#3845.
This is a large change to how io_buffers are filled. The essential problem
comes about with code like (example):
echo ( /bin/pwd )
The output of /bin/pwd must go to fish, not the tty. To arrange for this,
fish does the following:
1. Invoke pipe() to create a pipe.
2. Add an io_bufferfill_t redirection that owns the write end of the pipe.
3. After fork (or equiv), call dup2() to replace pwd's stdout with this pipe.
Now when /bin/pwd writes, it will send output to the read end of the pipe.
But who reads it?
Prior to this fix, fish would do the following in a loop:
1. select() on the pipe with a 10 msec timeout
2. waitpid(WNOHANG) on the pwd proc
This polling is ugly and confusing and is what is replaced here.
With this new change, fish now reads from the pipe via a background thread:
1. Spawn a background pthread, which select()s on the pipe's read end with
a long (100 msec) timeout.
2. In the foreground, waitpid() (allowing hanging) on the pwd proc.
The big win here is a major simplification of job_t::continue_job() since
it no longer has to worry about filling buffers. This will make things
easier for concurrent execution.
It may not be obvious why the background thread still needs a poll (100 msec).
The answer is for cases where the write end of the fd escapes, in particular
background processes invoked inside command substitutions. psub is perhaps
the only important case of this (other shells typically just hang here).
This makes some significant architectual improvements to io_pipe_t and
io_buffer_t.
Prior to this fix, io_buffer_t subclassed io_pipe_t. io_buffer_t is now
replaced with a class io_bufferfill_t, which does not subclass pipe.
io_pipe_t no longer remembers both fds. Instead it has an autoclose_fd_t,
so that the file descriptor ownership is clear.
This switches IO redirections after fork() to use the dup2_list_t,
instead of io_chain_t. This results in simpler code with much simpler
error handling.
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.
This is a large change to how io_buffers are filled. The essential problem
comes about with code like (example):
echo ( /bin/pwd )
The output of /bin/pwd must go to fish, not the tty. To arrange for this,
fish does the following:
1. Invoke pipe() to create a pipe.
2. Add an io_bufferfill_t redirection that owns the write end of the pipe.
3. After fork (or equiv), call dup2() to replace pwd's stdout with this pipe.
Now when /bin/pwd writes, it will send output to the read end of the pipe.
But who reads it?
Prior to this fix, fish would do the following in a loop:
1. select() on the pipe with a 10 msec timeout
2. waitpid(WNOHANG) on the pwd proc
This polling is ugly and confusing and is what is replaced here.
With this new change, fish now reads from the pipe via a background thread:
1. Spawn a background pthread, which select()s on the pipe's read end with
a long (100 msec) timeout.
2. In the foreground, waitpid() (allowing hanging) on the pwd proc.
The big win here is a major simplification of job_t::continue_job() since
it no longer has to worry about filling buffers. This will make things
easier for concurrent execution.
It may not be obvious why the background thread still needs a poll (100 msec).
The answer is for cases where the write end of the fd escapes, in particular
background processes invoked inside command substitutions. psub is perhaps
the only important case of this (other shells typically just hang here).
This makes some significant architectual improvements to io_pipe_t and
io_buffer_t.
Prior to this fix, io_buffer_t subclassed io_pipe_t. io_buffer_t is now
replaced with a class io_bufferfill_t, which does not subclass pipe.
io_pipe_t no longer remembers both fds. Instead it has an autoclose_fd_t,
so that the file descriptor ownership is clear.
This switches IO redirections after fork() to use the dup2_list_t,
instead of io_chain_t. This results in simpler code with much simpler
error handling.
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