Commit graph

325 commits

Author SHA1 Message Date
ridiculousfish
e84dad5432 Rationalize null handling in disown_job
disown_job had some extraneous null checks that could not happen in
practice. Simplify this code.
2021-10-25 16:13:00 -07:00
ridiculousfish
7a1c005b42 Switch to using timef instead of gettimeofday
This encapsulates the tricky arithmetic inside timef(), which uses
gettimeofday.
2021-08-27 16:25:33 -07:00
ridiculousfish
7d537eefbb proc_get_jiffies to accept pid directly
No need to accept the mutable proc here.
2021-08-27 13:05:27 -07:00
ridiculousfish
33f3c03dae Allow on-job-exit handlers to be added for any pid in the job
Prior to this change, a function with an on-job-exit event handler must be
added with the pgid of the job. But sometimes the pgid of the job is fish
itself (if job control is disabled) and the previous commit made last_pid
an actual pid from the job, instead of its pgroup.

Switch on-job-exit to accept any pid from the job (except fish itself).
This allows it to be used directly with $last_pid, except that it now
works if job control is off. This is implemented by "resolving" the pid to
the internal job id at the point the event handler is added.

Also switch to passing the last pid of the job, rather than its pgroup.
This aligns better with $last_pid.
2021-05-25 15:28:53 -07:00
ridiculousfish
f3d78e21d1 Switch last_pid from the pgroup to the actual last pid
When a job is placed in the background, fish will set the `$last_pid`
variable. Prior to this change, `$last_pid` was set to the process group
leader of the job. However this caussed problems when the job ran in
fish's process group, because then fish itself would be the process group
leader and commands like `wait` would not work.

Switch `$last_pid` to be the actual last pid of the pipeline. This brings
it in line with the `$!` variable from zsh and bash.

This is technically a breaking change, but it is unlikely to cause
problems, because `$last_pid` was already rather broken.

Fixes #5036
Fixes #5832
Fixes #7721
2021-05-25 15:28:53 -07:00
ridiculousfish
504a969a24 Separate on-job-exit and and on-process-exit events
It is possible to run a function when a process exits via `function
--on-process-exit`, or when a job exits via `function --on-job-exits`.
Internally these were distinguished by the pid in the event: if it was
positive, then it was a process exit. If negative, it represents a pgid
and is a job exit. If zero, it fires for both jobs and processes, which is
pretty weird.

Switch to tracking these explicitly. Separate out the --on-process-exit
and --on-job-exit event types into separate types. Stop negating pgids as
well.
2021-05-19 11:29:08 -07:00
ridiculousfish
6d00ad1045 Ensure that on-process-exit events fire for reaped jobs
This ensures that if a job exits before we have set up the
on-process-exit handler, the handler will still fire.

Fixes #7210
2021-05-17 15:28:32 -07:00
ridiculousfish
60d75e9aa0 Remove proc_create_event
Switch to a set of factory functions inside event_t.
No user-visible change here.
2021-05-17 15:26:59 -07:00
ridiculousfish
962b0f8b90 Pass $status to process-exit event handlers in all cases
Previously, an event handler would receive -1 if the process exited due
to a signal. Instead pass the same value as $status.
2021-05-17 15:25:27 -07:00
ridiculousfish
82fd8fe9fb Refactor wait handles
In preparation for using wait handles in --on-process-exit events, factor
wait handles into their own wait handle store. Also switch them to
per-process instead of per-job, which is a simplification.
2021-05-17 15:25:21 -07:00
ridiculousfish
632e150152 Introduce notion of "wait handles"
This is preparing to address the problem where fish cannot wait on a
reaped job, because it only looks at the active job list. Introduce the
idea of a "wait handle," which is a thing that `wait` can use to check if
a job is finished. A job may produce its wait handle on demand, and
parser_t will save the wait handle from wait-able jobs at the point they
are reaped.

This change merely introduces the idea; the next change makes builtin_wait
start using it.
2021-05-15 20:20:50 -07:00
ridiculousfish
0a559ac457 Reformat source files with clang-format 2021-04-21 13:31:58 -07:00
ridiculousfish
467755bf4a Bravely optimize job_reap
job_reap is now called more often. This optimizes it by doing an
early-out if there are no running jobs (common at the prompt) and also
skipping the save/restore status, since by inspection we also save and
restore the status when running event handlers.
2021-04-17 16:43:28 -07:00
ridiculousfish
3b32a32dda Replace some format_strings with to_string
This is hopefully a little faster and a little safer as there's
no format string involved.
2021-04-17 16:43:27 -07:00
ridiculousfish
be9579418f Refactor to use has_external_proc instead of a manual loop
No functional change here.
2021-04-17 16:43:27 -07:00
ridiculousfish
e299f89db3 Rename print_job_summary to call_job_summary
No functional change; this is simply a less misleading name.
2021-04-17 16:43:27 -07:00
ridiculousfish
a69e94d954 add_disowned_job to accept its parameter by const pointer
It never modified the job.
2021-04-03 21:05:32 -07:00
ridiculousfish
b44f40547b Rationalize exit codes for failed execs
This cleans up some exit code processing. Previously a failed exec
would produce exit code 125 unconditionally, while a failed posix_spawn
would produce exit code 1 (!).

With this change, fish reports exit code 126 for not-executable, and 127
for file-not-found. This matches bash.
2021-03-27 21:37:46 -07:00
Fabian Homborg
371516382d Create job-exit caller events inside event handlers
f7e2e7d26b forbid any job exit events
from happening inside jobs that were themselves event handlers, but
that causes e.g.

```fish
function f --on-event fish_prompt
source (echo "echo hello world" | psub)
end
```

to not trigger psub's cleanup, so it leaves files in $TMPDIR behind.

This was hit by pyenv, because that still uses `source (thing |
psub)`.

Fixes #7792.
2021-03-07 10:00:52 +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
7c4891407f Remove restore_attrs from terminal_return_from_job_group function
Previously this parameter was used to more-eagerly restore the terminal
mode. This was the basis for #2214. However now we restore the mode
from the reader instead, so we can remove this unused parameter.
2020-11-23 19:36:55 -08:00
ridiculousfish
db514df95b Stop setting tty back to shell mode when a fg proc completes
Prior to this change, when a process resumes because it is brought back
to the foreground, we would reset the terminal attributes to shell mode.
This fixed #2114 but subtly introduced #7483.

This backs out 9fd9f70346, re-introducing #2114 and re-fixing #7483.
A followup fix will re-fix #2114; these are broken out separately for
bisecting purposes.

Fixes #7483.
2020-11-23 19:36:39 -08:00
Fabian Homborg
b32540f346 proc: Remove unused function 2020-11-15 11:26:45 +01:00
ridiculousfish
2a8e104cc8 Relax some main thread requirements around waiting for jobs
This is now correctly per-parser so the thread should no longer matter.
2020-09-13 17:54:52 -07:00
Johannes Altmanninger
fbaa5d193d Declare functions in headers or use internal linkage (static)
Found with gcc's -Wmissing-declarations which gives warnings like

	../src/tinyexpr.cpp:61:5: warning: no previous declaration for ‘int get_arity(int)’ [-Wmissing-declarations]
	   61 | int get_arity(const int type) {

The same warnings show up for builtin functions like builtin_bg because they
currently don't include their own headers. I left that.
Also reformat the touched files.
2020-09-08 22:44:03 +02:00
ridiculousfish
3062994645 Implement cancel groups
This concerns how "internal job groups" know to stop executing when an
external command receives a "cancel signal" (SIGINT or SIGQUIT). For
example:

    while true
        sleep 1
    end

The intent is that if any 'sleep' exits from a cancel signal, then so would
the while loop. This is why you can hit control-C to end the loop even
if the SIGINT is delivered to sleep and not fish.

Here the 'while' loop is considered an "internal job group" (no separate
pgid, bash would not fork) while each 'sleep' is a separate external
command with its own job group, pgroup, etc. Prior to this change, after
running each 'sleep', parse_execution_context_t would check to see if its
exit status was a cancel signal, and if so, stash it into an int that the
cancel checker would check. But this became unwieldy: now there were three
sources of cancellation signals (that int, the job group, and fish itself).

Introduce the notion of a "cancellation group" which is a set of job
groups that should cancel together. Even though the while loop and sleep
are in different job groups, they are in the same cancellation group. When
any job gets a SIGINT or SIGQUIT, it marks that signal in its cancellation
group, which prevents running new jobs in that group.

This reduces the number of signals to check from 3 to 2; eventually we can
teach cancellation groups how to check fish's own signals and then it will
just be 1.
2020-09-03 11:01:27 -07:00
ridiculousfish
0b075fce88 Factor the exit state to make exit handlers more explicit
This adds a new type 'exit_state_t' which encapsulates where fish is in
the process of exiting. This makes it explicit when fish wants to cancel
"ordinary" fish script but still run exit handlers.

There should be no user-visible behavior change here; this is just
refactoring in preparation for the next commit.
2020-08-30 15:09:31 -07:00
Johannes Altmanninger
09f189870e Trigger prompt repaint after printing parser error or background job warning
See #7289
2020-08-27 21:18:26 +02:00
ridiculousfish
d50c0c2b85 Prevent certain 100% CPU loops
We weren't correctly updating the internal exit generation value. This
meant that if one internal process exits, every other internal process
that has not exited will continually check, leading to 100% CPU usage.

I think this mainly affects concurrent mode, but it may be reproducible
if you have a command which refuses to consume its input.
2020-08-16 12:56:42 -07:00
Fabian Homborg
103a4ece81 Add parens to silence warning
This triggered -Wparentheses in gcc 10.1.0
2020-08-08 09:14:47 +02: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
206b2d0a26 Simplify topic monitoring
The topic monitor allows a client to wait for multiple events, e.g. sigchld
or an internal process exit. Prior to this change a client had to specify
the list of generations and the list of topics they are interested in.
Simplify this to just the list of generations, with a max-value generation
meaning the topic is not interesting.

Also remove the use of enum_set and enum_array, it was too complex for what
it offered.
2020-08-06 19:01:30 -07:00
Soumya
8dd2d4f15d Change builtins to return maybe_t<int> instead of int 2020-08-05 12:23:49 -07:00
Soumya
a2b2bcef6e Add a $status_generation variable that's incremented for each interactive command that produces a status.
This can be used to determine whether the previous command produced a real status, or just carried over the status from the command before it. Backgrounded commands and variable assignments will not increment status_generation, all other commands will.
2020-08-05 12:23:49 -07:00
ridiculousfish
87d049edd8 Remove redirect_tty_output call from tcgetattr return
tcgetattr cannot return EIO.
2020-08-03 16:42:27 -07:00
ridiculousfish
c9b42c6f1f Stop #include-ing wcstringutil.h in flog.h
This is a header dependency that we can break.
2020-07-29 17:04:18 -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
3382bc70d2 Fix a stale comment
[ci skip]
2020-07-27 15:36:43 -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
Mahmoud Al-Qudsi
d46b9ff9be Remove repeated acquire of disowned pid lock in a loop 2020-07-25 20:45:08 -05: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
David Adam
025a0d3cf5 proc: add log message for reaped disowned IDs 2020-07-25 20:35:54 -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
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
37dc554fe1 Revert "Remove unnecessary owning_lock usages"
This reverts commit 3a5585df95.

This reverts a change that removed a lock. It's indeed true that in master,
fish script is bound to the main thread. But I'm working to remove that
limitation and these locks are important in that future.
2020-07-12 18:56:39 -07:00
Mahmoud Al-Qudsi
3a5585df95 Remove unnecessary owning_lock usages
The owning locks were added after the original code and decorated with
comments indicating they are thread-safe, even though they're only ever
used from the main thread. Presuming the intent was to make future
manipulation of the code safer rather than to actually make use of any
thread safety guarantees, these have been wrapped in a new
`thread_exclusive` type which always calls ASSERT_IS_MAIN_THREAD.

The benefit is that this does not perform a syscall to lock a mutex
each time the variables are accessed.
2020-07-12 20:21:28 -05:00