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`.