Commit graph

76 commits

Author SHA1 Message Date
ridiculousfish
d578f8d136 separated_buffer_t to accept strings by rvalue reference
This saves a copy in some cases.
2021-02-04 16:02:40 -08:00
ridiculousfish
032467f338 separated_buffer_t to stop being a template
Now that we no longer construct wide separated buffers, it doesn't have
to be templatized.
2021-02-04 15:32:11 -08:00
ridiculousfish
7d494eab5c builtins to write to buffers directly
This concerns builtins writing to an io_buffer_t. io_buffer_t is how fish
captures output, especially in command substitutions:

    set STUFF (string upper stuff)

Recall that io_buffer_t fills itself by reading from an fd (typically
connected to stdout of the command). However if our command is a builtin,
then we can write to the buffer directly.

Prior to this change, when a builtin anticipated writing to an
io_buffer_t, it would first write into an internal buffer, and then after
the builtin was finished, we would copy it to the io_buffer_t. This was
because we didn't have a polymorphic receiver for builtin output: we
always buffered it and then directed it to the io_buffer_t or file
descriptor or stdout or whatever.

Now that we have polymorphpic io_streams_t, we can notice ahead of time
that the builtin output is destined for an internal buffer and have it
just write directly to that buffer. This saves a buffering step, which is
a nice simplification.
2021-02-04 15:21:32 -08:00
ridiculousfish
cd9a035f02 Add a string_output_stream_t to collect builtin output
This is used when creating a function; this breaks a dependency on the
more complicated buffered_output_stream_t to ease refactoring.
2021-02-04 14:12:14 -08:00
ridiculousfish
86a12e1abd separated_buffer_t::append to stop being a template
In preparation for simplifying how builtins write to buffers, make
append an ordinary function rather than a template function.
2021-02-04 13:19:11 -08:00
ridiculousfish
d5d09c993e io_buffer_t to explicitly poke its item when closing
io_buffer_t is used to buffer output from a command substitution, so we
can split it into arguments. Typically io_buffer_t reads from its pipe
until it gets EOF and then stops reading. However it may be that the
cmdsub ends but EOF is not delivered because the stdout of the cmdsub
escaped with a background process.

Prior to this change we would wake up every 100 msec (select timeout) to
check if the cmdsub is finished. However this 100 msec adds latency if a
background process is launched from e.g. fish_prompt.

Switch to the new poke() function. Now when the cmdsub is finished, it
pokes its item, which explicitly wakes it up. This removes the extra
latency.

Fixes #7559
2021-01-07 11:54:31 -08:00
ridiculousfish
38a30d1798 Mark subclasses of io_data_t as final 2020-12-19 20:06:36 -08:00
ridiculousfish
d1dab22691 Ensure we don't leak half of a pipe
It was possible though unlikely for make_autoclose_pipes to close only
one side of pipe, if it fails to find a new fd. This would result in an
fd leak. Ensure that doesn't happen.
2020-09-05 13:24:26 -07:00
ridiculousfish
81a39be0bb Support explicitly separated output on stderr
In principle this would allow 'string split' or whatever to output to
stderr and not lose the item separation. In practice this is not used
but it fixes a TODO.
2020-07-30 23:00:34 -07:00
ridiculousfish
bcfc54fdaa Do not buffer builtin output if avoidable
builtins output to stdout and stderr via io_streams_t. Prior to this fix, it
contained an output_stream_t which just wraps a buffer. So all builtin output
went to this buffer (except for eval).

Switch output_stream_t to become a new abstract class which can output to a
buffer, file descriptor, or nowhere. This allows for example `string` to stream
its output as it is produced, instead of buffering it.
2020-07-30 22:45:44 -07:00
ridiculousfish
7cc99a2d80 Rename job_tree to job_group
Initially I wanted to pick a different name to avoid confusion with
process groups, but really job trees *are* process groups. So name them
to reflect that fact.

Also rename "placeholder" to "internal" which is clearer.
2020-05-30 14:22:44 -07:00
ridiculousfish
a86d3f4136 Remove job_lineage_t
Its responsibilities are now subsumed by job_tree_t except for
the block_io which we pass around explicitly.
2020-05-30 14:22:44 -07:00
ridiculousfish
e95bcfb074 Teach a job to decide its job tree
Job trees come in two flavors: “placeholders” for jobs which are only fish
functions, and non-placeholders which need to track a pgid. This adds
logic to allow a job to decide if its parent's job tree is appropriate,
and allocating a new tree if not.
2020-05-30 14:22:43 -07:00
Mahmoud Al-Qudsi
bc756a981e Recover from bad redirections in the middle of a job pipeline
Currently fish aborts execution mid-pipeline if a file redirection
failed, which can leave the shell in a broken state (job abandoned after
giving control of the terminal to an already-executed job in the
pipeline).

This patch replaces a failed fd with a closed fd and continues execution
if the affected process wasn't the first in the pipeline.

While this is a hack to address the regression behind fish-shell/#7038
introduced in d62576c, it can also be argued that this behavior is
actually more correct... right?

Closes #7038.
2020-05-30 00:27:11 -05:00
Rosen Penev
0668513138 Change C casts to C++ ones
Some were kept for compatibility.

Found with -Wold-style-cast

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-05-01 13:30:56 -07:00
ridiculousfish
607779257c Introduce out_is_piped and err_is_piped on io_streams_t
builtin_eval needs to know whether to set up bufferfills to capture its
output and/or errput; it should do this specifically if the output and
errput is piped (and not, say, directed to a file). In preparation for
this change, add bools to io_streams_t which track whether stdout and
stderr are specifically piped.
2020-04-28 09:59:55 -07:00
ridiculousfish
a1f1b9c2d9 builtin_eval to direct output to its iostreams
Prior to this fix, builtin_eval would direct output to the io_chain of the
job. The problem is with pipes: `builtin_eval` might happily attempt to
write unlimited output to the write end of a pipe, but the corresponding
reading process has not yet been launched. This results in deadlock.

The fix is to buffer all the output from `builtin_eval`. This is not fun
but the best that can be done until we have real concurrent processes.

Fixes #6806
2020-04-26 11:05:50 -07:00
ridiculousfish
82f2d86718 Thread pgroups into builtin_eval
Ensure that if eval is invoked as part of a pipeline, any jobs spawned
by eval will have the same pgroup as the parent job.

Partially fixes #6806
2020-04-26 11:05:50 -07:00
ridiculousfish
a765026c4c Adopt fd_monitor in bufferfill
This switches bufferfills from using an exclusively-owned thread, to
sharing an fd_monitor. This allows multiple bufferfills to all use the same
thread.
2020-02-05 12:05:39 -08:00
Fabian Homborg
3bb15defbb
Replace debug() with flog
PR #6511 

Flog has the advantage of having *categories*, not severities, so it'll be easier to get output for a certain subsystem now.
2020-01-26 14:13:17 +01:00
ridiculousfish
4f205f38b4 Clean up a few bits about discarding buffers
We weren't properly propagating the 'discarded' stuff from output
streams to buffers. Fix that.
2020-01-24 16:08:56 -08:00
Fabian Homborg
024e03ab1e Replace debug(1) with FLOGF(warning) 2020-01-19 14:22:39 +01:00
ridiculousfish
c963442999 Collapse io_data switch statements
Now that each io_data knows its source and target fd, we don't need to switch
on its types any more.
2019-12-29 15:51:22 -08:00
ridiculousfish
0af5608ce8 io_data_t to store the source_fd directly
Now that all io_data_ts know their source fd, just store it directly in
the base class. This will simplify some uses of io_data_t.
2019-12-29 15:14:08 -08:00
ridiculousfish
d0cefe8b65 Always mark pipes as cloexec
There is never a reason to keep these open in exec.
2019-12-29 14:57:16 -08:00
ridiculousfish
9f7972a08b clang-format C++ files 2019-12-29 14:25:42 -08:00
ridiculousfish
2e7cbaeaba Remove io_file_t::is_dev_null
This is no longer used.
2019-12-20 14:47:54 -08:00
ridiculousfish
0531c02ce4 Remove 'user_supplied' flag for io_fd_t
user_supplied was used to distinguish IO redirections which were
explicit, vs those that came about through "transmogrphication." But
transmogrification is no more. Remove the flag.
2019-12-19 14:14:23 -08:00
ridiculousfish
1f83fb47ce Finish the IO cleanup.
Remove some dead code and add missing dtors.
2019-12-12 17:47:08 -08:00
ridiculousfish
33aff87c10 Switch io_file_t to store an fd, not a path
Prior to this fix, a file redirection was turned into an io_file_t. This is
annoying because every place where we want to apply the redirection, we
might fail due to open() failing. Switch to opening the file at the point
we resolve the redirection spec. This will simplify a lot of code.
2019-12-12 17:34:40 -08:00
ridiculousfish
af473d4d0c Introduce redirection_spec_t
Prior to this change, a process after it has been constructed by
parse_execution, but before it is executed, was given a list of
io_data_t redirections. The problem is that redirections have a
sensitive ownership policy because they hold onto fds. This made it
rather hard to reason about fd lifetime.

Change these to redirection_spec_t. This is a textual description
of a redirection after expansion. It does not represent an open file and
so its lifetime is no longer important.

This enables files to be held only on the stack, and are no longer owned
by a process of indeterminate lifetime.
2019-12-12 16:44:24 -08:00
ridiculousfish
be685faeb8 Clean up how pipe fd avoidance works
fish has to ensure that the pipes it creates do not conflict with any
explicit fds named in redirections. Switch this code to using
autoclose_fd_t to make the ownership logic more explicit, and also
introduce fd_set_t to reduce the dependence on io_chain_t.
2019-12-12 14:58:18 -08:00
ridiculousfish
970288c854 Migrate the read limit into parser_t::libdata
It is more natural here than "on the last bufferfill."
2019-12-11 11:50:52 -08:00
ridiculousfish
0573e95b03 Resurrect io_print 2019-12-10 17:18:37 -08:00
ridiculousfish
b5d0075406 Use iothread pool for background fillthreads
Background fillthreads are used when we want to populate a buffer from an
external command. The most common is command substitution.

Prior to this commit, fish would spin up a fillthread whenever required.
This ended up being quite expensive.

Switch to using the iothread pool instead. This enables reusing the same
thread(s), which prevents needing to spawn new threads. This shows a big
perf win on the alias benchmark (766 -> 378 ms).
2019-11-27 12:03:56 -08:00
Rosen Penev
69d0bb7c0d io.h: Add missing override
Found with clang's -Winconsistent-missing-destructor-override

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2019-11-25 14:50:40 -08:00
ridiculousfish
9023c2187f Make shutdown_fillthread_ a relaxed_atomic_bool_t
Reduces the noisiness of working with it.
2019-11-23 14:12:34 -08:00
ridiculousfish
ac2eed2ffa Make io_chain_t store const io_data_t
This will make it easier to reason about with concurrent execution.
2019-11-10 14:00:30 -08:00
ridiculousfish
521d0e84f5 Remove non-const get_io_for_fd
These could be made unused.
2019-11-10 13:41:12 -08:00
ridiculousfish
f2093aef43 Remove io_chain_t::push_front
It was unused.
2019-11-10 13:25:55 -08:00
ridiculousfish
554ee240b3 Correct handling of explicitly separated output when all elements are empty
Previously when propagating explicitly separated output, we would early-out
if the buffer was empty, where empty meant contains no characters. However
it may contain one or more empty strings, in which case we should propagate
those strings.

Remove this footgun "empty" function and handle this properly.

Fixes #5987
2019-07-21 14:00:27 -07:00
ridiculousfish
6ce85aebc6 Switch file_io_t to store a wcstring
We no longer use file_io_t after fork(). We don't need to use a malloc'd
string any more. Use a wcstring.
2019-06-09 17:43:25 -07:00
Fabian Homborg
c2970f9618 Reformat all files
This runs build_tools/style.fish, which runs clang-format on C++, fish_indent on fish and (new) black on python.

If anything is wrong with the formatting, we should fix the tools, but automated formatting is worth it.
2019-05-05 12:09:25 +02:00
ridiculousfish
3bbee06248 Introduce the notion of a deferred process
In a job, a deferred process is the last fish internal process which pipes
to an external command. Execute the deferred process last; this will allow
for streaming its output.
2019-03-24 14:27:23 -07:00
Aaron Gyes
d5ac239f68 This commit changes wchar.h includes to cwchar, and uses std::
for everything it provides.
2019-03-12 15:09:36 -07:00
ridiculousfish
0b3eca1743 Cleanup handle_builtin_output
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.
2019-02-17 14:17:44 -08:00
ridiculousfish
2e542d7822 Initialize shutdown_fillthread_ to false
It was left uninitialized which was causing certain command substitutions
to exit too early.

Fixes #5616
2019-02-05 21:44:43 -08:00
ridiculousfish
6f682c8405 Fill io_buffer via background thread
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).
2019-02-03 01:58:49 -08:00
ridiculousfish
178b72b2fd io_buffer_t becomes io_bufferfill_t
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.
2019-02-03 01:58:49 -08:00
ridiculousfish
dbe906b79e Introduce dup2_list_t
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.
2019-02-03 01:58:49 -08:00