Commit graph

161 commits

Author SHA1 Message Date
ridiculousfish
fb92ad946b Rework null terminated arrays
Several functions including wgetopt and execve operate on null-terminated
arrays of nul-terminated pointers: a list of pointers to C strings where
the last pointer is null. Prior to this change, each process_t stored its
argv in such an array. This had two problems:

1. It was awkward to work with this type, instead of using std::vector,
etc.
2. The process's arguments would be rearranged by builtins which is
surprising

Our null terminated arrays were built around a fancy type that would copy
input strings and also generate an array of pointers to them, in one big
allocation.

Switch to a new model where we construct an array of pointers over
existing strings. So you can supply a `vector<string>` and now
`null_terminated_array_t` will just make a list of pointers to them. Now
processes can just store their argv in a familiar wcstring_list_t.
2021-03-28 15:31:25 -07:00
ridiculousfish
e0e4b11dbd Make arguments to builtins const
Prior to this change, builtins would take their arguments as `wchar_t **`.
This implies that the order of the arguments may be changed (which is
true, `wgetopter` does so) but also that the strings themselves may be
changed, which no builtin should do.

Switch them all to take `const wchar_t **` instead: now the arguments may
be rearranged but their contents may no longer be modified.
2021-03-28 15:31:25 -07:00
Ethel Morgan
5a0aa7824f Saturate exit codes to 255 for all builtins
After commit 6dd6a57c60, 3 remaining
builtins were affected by uint8_t overflow: `exit`, `return`, and
`functions --query`.

This commit:
- Moves the overflow check from `builtin_set_query` to `builtin_run`.
- Removes a conflicting int -> uint8_t conversion in `builtin_return`.
- Adds tests for the 3 remaining affected builtins.
- Simplifies the wording for the documentation for `set --query`.
- Does not change documentation for `functions --query`, because it does
  not state the exit code in its API.
- Updates the CHANGELOG to reflect the change to all builtins.
2021-02-13 08:41:51 +01:00
ridiculousfish
2caeec24f7 Tighten up pipeline-aborting errors
Prior to this change, the functions in exec.cpp would return true or false
and it was not clear what significance that value had.

Switch to an enum to make this more explicit. In particular we have the
idea of a "pipeline breaking" error which should us to skip processes
which have not yet launched; if no process launches then we can bail out
to a different path which avoids reaping processes.
2020-12-13 17:30:26 -08:00
ridiculousfish
a2e486966a Always become pgroup leader in interactive mode
Prior to this change, if fish were launched connected to a tty but not as
pgroup leader, it would attempt to become pgroup leader only if
--interactive is explicitly passed. But bash will unconditionally attempt
to become pgroup leader if launched interactively. This can result in
scenarios where fish is running interactively but in another pgroup. The
most obvious impact is that control-C will result in the pgroup leader
(not fish) exiting and make fish orphaned.

Switch to matching the bash behavior here - we will always try to become
pgroup leader if interactive.

Fixes #7060.
2020-12-06 13:42:35 -08:00
ridiculousfish
6c4d6dc4a9 Make the 'time' keyword a fixed property of a job.
The 'time' prefix may come about either because the job itself is marked
with time, or because of the "inside out" weirdness of 'not time...'.
Factor this logic together and precompute it for a job.
2020-09-02 15:06:17 -07:00
ridiculousfish
2cd336376e Refactor process_mark_finished_children
Reduce the level of nesting and the loop complexity.
2020-08-07 12:34:53 -07:00
ridiculousfish
26fda2bf0d Improve some formatting in proc.h 2020-08-07 11:38:47 -07:00
Soumya
8dd2d4f15d Change builtins to return maybe_t<int> instead of int 2020-08-05 12:23:49 -07:00
ridiculousfish
3506274ccf Make in_foreground an explicit param to continue_job
This moves us slightly closer towards fish code in the background. The idea is
that a background job may still have "foreground" sub-jobs, example:

    begin ; sleep 5 ; end &

The begin/end job runs in the background but should wait for `sleep`.

Prior to this fix, fish would see the overall job group is in the background
and not wait for any of its processes. With this change we detach waiting from
is_foreground.
2020-07-27 15:56:24 -07:00
ridiculousfish
c35fe879c7 Bravely remove reclaim... param from continue_job, and rework tcsetpgrp calls
This changes how fish attempts to protect itself from calling tcsetpgrp() too
aggressively. Recall that tcsetpgrp() will "force" itself, if SIGTTOU is
ignored (which it is in fish when job control is enabled).

Prior to this fix, we avoided SIGTTINs by only transferring the tty ownership
if fish was already the owner. This dated from a time before we had really
nailed down how pgroups should be assigned. Now we more deliberately assign a
job's pgroup so we don't need this conservative check.

However we still need logic to avoid transferring the tty if fish is not the
owner. The bad case is when job control is enabled while fish is running in the
background - here fish would transfer the tty and "steal" from the foreground
process.

So retain the checks of the current tty owner but migrate them to the point of
calling tcsetpgrp() itself.
2020-07-27 14:51:37 -07:00
ridiculousfish
1823f5d95f Remove the send_sigcont from continue_job
We can just send sigcont if the job is stopped; no need to make this an
explicit param.
2020-07-27 10:48:32 -07:00
David Adam
2720f3d2ef proc: disown PIDs, not just PGIDs
add_disowned_pgid skipped jobs that have a PGID equal to the running
process. However, this includes processes started in config.fish or when
job control is turned off, so they never get waited on.

Instead, refactor this function to add_disowned_job, and add either the PGID or
all the PIDs of the job to the list of disowned PIDs/PGIDs.

Fixes #7183.
2020-07-25 20:38:59 -05:00
ridiculousfish
54b642bc6f Factor job groups into their own file
Migrate out of proc.h, which has become too long.
2020-07-19 16:42:29 -07:00
ridiculousfish
56e250d467 Remove a commented-out field 2020-07-19 15:48:16 -07:00
ridiculousfish
7f8c00c20a Remove job_t::wants_terminal
This now lives in the job group, not individual jobs.
2020-07-18 12:42:44 -07:00
ridiculousfish
ba8b89873e Teach a job its command at constructor time
No point in allowing this to be set later.
2020-07-18 12:42:44 -07:00
ridiculousfish
f30ce21aaa terminal_maybe_give_to_job to operate on groups, not jobs
Assigning the tty is really a function of a job group, not an individual
job. Reflect that in terminal_maybe_give_to_job_group and also
terminal_return_from_job_group.
2020-07-18 12:42:44 -07:00
ridiculousfish
40c9bda7fd Store the command that produced a job group in the group
This will enable us to replace more uses of jobs with job groups.
2020-07-18 12:42:44 -07:00
ridiculousfish
2a4c545b21 Rework how signals trigger cancellation
When fish receives a "cancellation inducing" signal (SIGINT in particular)
it has to unwind execution - for example while loops or whatever else that
is executing. There are two ways this may come about:

1. The fish process received the signal
2. A child process received the signal

An example of the second case is:

    some_command | some_function

Here `some_command` is the tty owner and so will receive control-C, but
then fish has to cancel function execution.

Prior to this change, these were handled uniformly: both would just set a
cancellation signal inside the parser. However in the future we will have
multiple parsers and it may not be obvious which one to set the flag in.
So instead distinguish these cases: if a process receives SIGINT we mark
the signal in its job group, and if fish receives it we set a global
variable.
2020-07-12 12:16:01 -07:00
ridiculousfish
2e5222ffe8 Finish renaming job tree to job group
Some "tree" terminology was still there.
2020-07-11 17:05:42 -07:00
ridiculousfish
765c48afa4 Migrate the notion of 'foreground' from job to job group
Whether a job is foreground is a property of its pgid, so it belongs
naturally on the job group.
2020-07-11 17:01:52 -07:00
ridiculousfish
0c22f67bde Remove the old parser bits
Now that everything has been migrated to the new AST, remove as much of
the parse_tree bits as possible
2020-07-04 14:58:05 -07:00
ridiculousfish
3534c07584 Adopt the new AST in parse_execution
parse_execution is what turns a parsed tree into jobs, etc. Switch it from
parse_tree to the new AST.
2020-07-04 14:58:05 -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
b119c4b3bb Eliminate pgroup_provenance_t
Now that job trees are a single source of truth for a job's pgid, we no
longer need fancy logic around how the pgroup is assigned.
2020-05-30 14:22:44 -07:00
ridiculousfish
f37a44db16 Migrate job pgid from job to job tree
Prior to this, jobs all had a pgid, and fish has to work hard to ensure
that pgids were inherited properly for nested jobs. But now the job tree
is the source of truth and there is only one location for the pgid.
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
a4b66d948b Add a property describing when a job is initially backgrounded
Track separately whether a job is in the background now, and whether
it was constructed in the background via the & syntax.
2020-05-30 14:22:44 -07:00
ridiculousfish
123f3e6f93 Put job_id into job_tree
Job IDs are really a property of a job tree, not individual jobs. Reflect
that fact by migrating job IDs into job_tree.
2020-05-30 14:22:44 -07:00
ridiculousfish
fe60f2ef16 Move root_has_job_control from lineage to job_tree
Whether we have job control is a property of the job tree, not of
individual jobs. Reflect that fact directly by moving it into the job tree.
2020-05-30 14:22:43 -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
ridiculousfish
4e01c06256 Introduce job_tree
job_tree represents the data that should be shared between a job and any
jobs that may be spawned by functions or eval run as part of that job. It
reifies shared data that before was handled piecemeal.
2020-05-30 14:22:43 -07:00
Johannes Altmanninger
6699a72e0e Handle child receiving SIGCONT
Fixes #6818
2020-03-27 20:30:58 +01:00
ridiculousfish
05b8d4de97 Make hup_background_jobs accept the job list directly 2020-02-19 20:35:04 -07:00
ridiculousfish
59c6663a16 Migrate the "are you sure you want to exit" logic from parse_execution to exec
This feels more like the sort of logic that should live in the point where
jobs are executed, instead of where jobs are created from parse trees.
2020-02-19 18:25:36 -07:00
ridiculousfish
6bf9ae9aeb Fix up --on-job-exit caller
The `function --on-job-exit caller` feature allows a command substitution
to observe when the parent job exits. This has never worked very well - in
particular it is based on job IDs, so a function that observes this will
run multiple times. Implement it properly.

Do this by having a not-recycled "internal job id".

This is only used by psub, but ensure it works properly none-the-less.
2020-02-08 16:23:25 -08:00
ridiculousfish
91df645c62 Make job_control a constant property of job_t
It no longer changes.
2020-02-08 14:14:37 -08:00
ridiculousfish
ce88e8739f Fix some speeling and improve a comment. 2020-02-08 13:15:33 -08:00
ridiculousfish
fba3c83ba5 Eliminate yet more calls to principal_parser()
In particular, remove job_t::from_job_id
2020-02-08 12:47:13 -08:00
ridiculousfish
f1f97b6476 Eliminate more calls to principal_parser()
Require a parser to get a job from its pgid.
2020-02-08 12:46:56 -08:00
ridiculousfish
8d8bcb7d8a Stop acquiring the terminal before running builtins
fish has some unprincipled code that attempts to tcsetpgrp() to own the
terminal before running a builtin; this was added because 'read' might
want to read from the terminal. I added this code before fully
understanding how process groups and terminals work. A better fix would
be to ensure that fish is marked as the pgroup leader in the job when
the builtin is the first process in the job, and we do that now.

Courageously back out the changes to grab the terminal; see #5147 and
also #5133.
2020-01-31 10:42:21 -08:00
ridiculousfish
a243e65939 Rename pgroup_mode to pgroup_provenance 2020-01-30 11:14:31 -08:00
ridiculousfish
10da6df506 Factor out logic about how pgroups are assigned
Introduce pgroup_provenance_t, a type which captures "where the pgroup
comes from." This centralizes some logic around how pgroups are
assigned, and it anticipates concurrent execution.
2020-01-30 10:50:16 -08:00
ridiculousfish
40ff4215a8 Express the "nested job control" idea directly
Prior to this fix, we would infer that nested jobs need job control.
Just pass that along explicitly in the job lineage.
2020-01-29 16:10:28 -08:00
Johannes Altmanninger
3de95038b0 Make "time" a job prefix
In particular, this allows `true && time true`, or `true; and time true`,
and both `time not true` as well as `not time true` (like bash).

time is valid only as job _prefix_, so `true | time true` could call
`/bin/time` (same in bash)

See discussion in #6442
2020-01-03 01:07:49 -06:00
Dan Zimmerman
8e17d29e04 Introduce the internal jobs for functions
This PR is aimed at improving how job ids are assigned. In particular,
previous to this commit, a job id would be consumed by functions (and
thus aliases). Since it's usual to use functions as command wrappers
this results in awkward job id assignments.

For example if the user is like me and just made the jump from vim -> neovim
then the user might create the following alias:
```
alias vim=nvim
```
Previous to this commit if the user ran `vim` after setting up this
alias, backgrounded (^Z) and ran `jobs` then the output might be:
```
Job	Group	State	Command
2	60267	stopped	nvim  $argv
```
If the user subsequently opened another vim (nvim) session, backgrounded
and ran jobs then they might see what follows:
```
Job	Group	State	Command
4	70542	stopped	nvim  $argv
2	60267	stopped	nvim  $argv
```
These job ids feel unnatural, especially when transitioning away from
e.g. bash where job ids are sequentially incremented (and aliases/functions
don't consume a job id).

See #6053 for more details.

As @ridiculousfish pointed out in
https://github.com/fish-shell/fish-shell/issues/6053#issuecomment-559899400,
we want to elide a job's job id if it corresponds to a single function in the
foreground. This translates to the following prerequisites:

- A job must correspond to a single process (i.e. the job continuation
    must be empty)
- A job must be in the foreground (i.e. `&` wasn't appended)
- The job's single process must resolve to a function invocation

If all of these conditions are true then we should mark a job as
"internal" and somehow remove it from consideration when any
infrastructure tries to interact with jobs / job ids.

I saw two paths to implement these requirements:

- At the time of job creation calculate whether or not a job is
  "internal" and use a separate list of job ids to track their ids.
  Additionally introduce a new flag denoting that a job is internal so
  that e.g. `jobs` doesn't list internal jobs
  - I started implementing this route but quickly realized I was
    computing the same information that would be computed later on (e.g.
    "is this job a single process" and "is this jobs statement a
    function"). Specifically I was computing data that populate_job_process
    would end up computing later anyway. Additionally this added some
    weird complexities to the job system (after the change there were two
    job id lists AND an additional flag that had to be taken into
    consideration)
- Once a function is about to be executed we release the current jobs
  job id if the prerequisites are satisfied (which at this point have
  been fully computed).
  - I opted for this solution since it seems cleaner. In this
  implementation "releasing a job id" is done by both calling
  `release_job_id` and by marking the internal job_id member variable to
  -1. The former operation allows subsequent child jobs to reuse that
  same job id (so e.g. the situation described in Motivation doesn't
  occur), and the latter ensures that no other job / job id
  infrastructure will interact with these jobs because valid jobs have
  positive job ids. The second operation causes job_id to become
  non-const which leads to the list of code changes outside of `exec.c`
  (i.e. a codemod from `job_t::job_id` -> `job_t::job_id()` and moving the
   old member variable to a non-const private `job_t::job_id_`)

Note: Its very possible I missed something and setting the job id to -1
will break some other infrastructure, please let me know if so!

I tried to run `make/ninja lint`, but a bunch of non-relevant issues
appeared (e.g. `fatal error: 'config.h' file not found`). I did
successfully clang-format (`git clang-format -f`) and run tests, though.
This PR closes #6053.
2019-12-31 10:08:50 -08:00
Rosen Penev
06cb0bbe9a
[clang-tidy] Add several references
Found with performance-unnecessary-value-param

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2019-12-26 21:55:53 -08:00
Mathieu Duponchelle
15c1b3ed4b Place fish in its own process group when launched with -i
Fixes #5909
2019-12-23 10:32:37 +01:00
ridiculousfish
d4daa28690 Correctly set the exit status in block and function processes
Previously, if the user control-C'd out of a process, we would set a
bogus exit status in the process, but it was difficult to observe this
because we would be cancelling anyways. But set it properly.
2019-12-17 18:19:38 -08:00