Conversation
|
The reported leak in the Fluent code can be suppressed by adding to the |
|
The reported leak in the Fluent code can be suppressed by adding
```text
leak:fish_fluent::AVAILABLE_LANGUAGES
```
to the `lsan_suppressions.txt` file. I'm fairly confident that this is a false positive, since the closure in `LazyLock::new()` should only run once and the leaked strings remain accessible, but ideally someone else should check if that's really the case.
yeah that looks like a false positive.
AIUI, LazyLock is the standardized verswion of once_cell::Lazy, so we should clean that up
I guess sanitize.sh is helpful when not using CMake,
so I guess we can add it.
|
build_tools/sanitize.sh
Outdated
| export FISH_TEST_MAX_CONCURRENCY=4 | ||
|
|
||
| export RUSTFLAGS=-Zsanitizer=address | ||
| export RUSTDOCFLAGS=-Zsanitizer=address |
There was a problem hiding this comment.
Yeah I think this is okay to add, these flags don't change very often.
As written, it's not really reusable, since it only works with check.sh.
When we want that, we well separate the check.sh-specific ones in an extra file.
Then we can replace them witha "cargo build" command.
That means we should group the variables needed only at compile time like RUSTFLAGS and RUSTDOCFLAGS before the options needed only at runtime like FISH_CI_SAN
There was a problem hiding this comment.
I pushed a version which puts the env vars needed at build time first.
I'm not sure if I entirely understand which kinds of reusability you have in mind. Are you suggesting to have a script which only sets options for enabling the sanitizer and then calls some configurable script/cargo command to run with these options set? And should changes beyond variable reordering be made in this PR?
From my side, these are the outstanding points to consider:
- Right now, we set
fast_unwind_on_malloc=0in CI, but not in the script added here (because I took the options from the Dockerfile which did not include this). Do we want to set this option? - The CI version contains comments about the
use_tlsoption, which might no longer be relevant. - I tried removing the
leak:AsanThreadsuppression and did not get any errors. Should we remove it (assuming it also causes no issues in CI)? ASAN_SYMBOLIZER_PATHis set in a somewhat hacky way in CI (541a069). Is this something we need to consider doing in the script as well? Or alternatively, is it still needed in CI?- Are there any other changes we want to make to the sanitizer options? It seems like they were last touched before the Rust rewrite.
- Do we want documentation about the new sanitize script?
There was a problem hiding this comment.
I'm not sure if I entirely understand which kinds of reusability you have in mind. Are you suggesting to have a script which only sets options for enabling the sanitizer and then calls some configurable script/cargo command to run with these
+options set? And should changes beyond variable reordering be made in this PR?
it would be nice to have a single source of truth for both CMake and Cargo-based builds
(source-able shell scripts for build-time and run-time variables?)
but asan is not really important for Rust and the config doesn't change a lot, so I'm fine with some duplication, and taking this as-is if it helps.
Maybe we should even remove asan, it should only help unsafe code.
From my side, these are the outstanding points to consider:
- Right now, we set
fast_unwind_on_malloc=0in CI, but not in the script added here (because I took the options from the Dockerfile which did not include this). Do we want to set this option?
that sounds like it should be kept for CI (slowness doesn't matter as much).
- The CI version contains comments about the
use_tlsoption, which might no longer be relevant.- I tried removing the
leak:AsanThreadsuppression and did not get any errors. Should we remove it (assuming it also causes no issues in CI)?
not sure but if doubt, we can remove both.
ASAN_SYMBOLIZER_PATHis set in a somewhat hacky way in CI (541a069). Is this something we need to consider doing in the script as well? Or alternatively, is it still needed in CI?
that's a workaround for Ubuntu not having llvm-symbolizer on PATH.
No strong opinion here.
- Do we want documentation about the new sanitize script?
the best documentation would be if the github workflow used it.
We can wait until then.
There was a problem hiding this comment.
source-able shell scripts for build-time and run-time variables?
That seems like a good idea if we keep using asan.
Maybe we should even remove asan, it should only help unsafe code.
We do have some unsafe blocks. Most of it seems to be wrappers around libc calls. Some of them could probably be replaced by nix crate wrappers. Not sure how useful asan actually is for fish. Has it found any issues in fish's Rust code before?
d971240 to
f34652d
Compare
|
Has it found any issues in fish's Rust code before?
yes, a stack-use-after-return due to illegal use of MaybeUninit's unsafe APIs
(not caught by any other tests because the UB happened to work IIRC).
To some extent we also want to find bugs in our dependencies (libc
implementations (like Cygwin) and said wrappers) but yeah it's not
super important, it's not our main focus.
If it ever causes too much maintenance burden, we can consider dropping it
|
310800f to
ae669aa
Compare
|
I extracted a script for setting the relevant env vars. For the CI job, it's not ideal, because Now that xtasks are on master, I also added one for sanitization. Not sure if we should keep the |
I think we can add Otherwise we can set it at build-time. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index afc9eab2cb..538f4a7457 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -71,14 +71,6 @@
ubuntu-asan:
runs-on: ubuntu-latest
- env:
- # Rust has two different memory sanitizers of interest; they can't be used at the same time:
- # * AddressSanitizer detects out-of-bound access, use-after-free, use-after-return,
- # use-after-scope, double-free, invalid-free, and memory leaks.
- # * MemorySanitizer detects uninitialized reads.
- #
- RUSTFLAGS: "-Zsanitizer=address"
- # RUSTFLAGS: "-Zsanitizer=memory -Zsanitizer-memory-track-origins"
steps:
- uses: actions/checkout@v6
# All -Z options require running nightly
@@ -104,11 +96,12 @@
cmake .. -DASAN=1 -DRust_CARGO_TARGET=x86_64-unknown-linux-gnu -DCMAKE_BUILD_TYPE=Debug
- name: make
run: |
+ . "$PWD/build_tools/set_asan_vars.sh" build-time
make -C build VERBOSE=1
- name: make fish_run_tests
run: |
set -x
- . "$PWD/build_tools/set_asan_vars.sh"
+ . "$PWD/build_tools/set_asan_vars.sh" run-time
export ASAN_SYMBOLIZER_PATH=$(command -v /usr/bin/llvm-symbolizer* | sort -n | head -1)
make -C build VERBOSE=1 fish_run_tests
that would be okay too
yeah that's a good direction. But no rush; if we get rid of CMake completely, this will happen automatically.
wouldn't
xtask would be good though maybe we should do that for |
ae669aa to
7d63bc9
Compare
|
I changed the approach to make I mostly adopted your diff for CI, except for passing arguments to the sourced script, because I don't think it's really necessary to complicate the script. The variables set for one step shouldn't interfere with the other step. One thing I'm not entirely sure about is whether |
build_tools/check.sh
Outdated
| export FISH_CHECK_RUST_TOOLCHAIN=nightly | ||
| export FISH_CHECK_CARGO_ARGS='-Zbuild-std' | ||
| # Build fails if this is not set. | ||
| FISH_CHECK_TARGET_TRIPLE="$(rustc --print host-tuple)" |
There was a problem hiding this comment.
we could maybe fail if any of these three variables is already set to non-empty.
We're unlikely to need to support that case but it can't hurt to prevent bad surprises.
There was a problem hiding this comment.
How about only setting them when they are undefined, and for FISH_CHECK_CARGO_ARGS prepending -Zbuild-std? This would allow testing with non-default values, and if invalid values are used compilation will fail, so there is not much gained by moving the failure into our script.
There was a problem hiding this comment.
ok that sounds reasonable as well
| export FISH_CHECK_CARGO_ARGS='-Zbuild-std' | ||
| # Build fails if this is not set. | ||
| FISH_CHECK_TARGET_TRIPLE="$(rustc --print host-tuple)" | ||
| export FISH_CHECK_TARGET_TRIPLE |
There was a problem hiding this comment.
any reason for not merging assignment + export?
There was a problem hiding this comment.
build_tools/check.sh
Outdated
| # Variables used at runtime | ||
|
|
||
| export FISH_CHECK_LINT=false | ||
| export FISH_TEST_MAX_CONCURRENCY=4 |
There was a problem hiding this comment.
maybe these two should not override user preference,
so maybe only set them to the smart default if unset or empty
export FISH_CHECK_LINT=${FISH_CHECK_LINT:-false}
export FISH_TEST_MAX_CONCURRENCY=${FISH_TEST_MAX_CONCURRENCY:-4}
it's a tradeoff of course but this seems the least surprising behavior.
It should not be annoying because we shouldn't really be in a situation where multiple devs want to have these variables set globally.
We can avoid that by picking good defaults.
There was a problem hiding this comment.
I agree that for FISH_CHECK_LINT, there is no good reason to override its value. One could even argue that there is no need to default to false, which might be less surprising and would mean that when the --sanitize flag is added, everything that is checked without it would still be checked.
For FISH_TEST_MAX_CONCURRENCY it was useful to have it set globally, but now that the test driver sets a reasonable default I think it makes sense to not override the var's value for asan checks.
There was a problem hiding this comment.
Hm, I just tested my suggested changes and noticed that if FISH_CHECK_LINT is not set to false, cargo deny fails when -Zbuild-std is passed to it. So we can
- always disable lints when
--sanitizeis passed - fail when
FISH_CHECK_LINTis set to a value other than false when--sanitizeis passed - build a more complex interface for specifying which cargo command gets which flags
There was a problem hiding this comment.
I think it would make sense to add a separate variable to house -Zbuild-std, and pass that only to the cargo commands that can stomach it.
But the other options sound fine as well; if it occasionally causes temporary inconvenience to users of sanitize builds, that's fine since we very rarely use those.
There was a problem hiding this comment.
The general problem with our approach of setting cargo arguments via a shared env var is that different subcommands take different options, but our cargo function blindly pastes options into the command line without taking the subcommand into account. If we want a non-hacky, general solution to this problem, I think we need to stop using the cargo function or make it subcommand-aware.
For the user interface, it depends whether we want to allow users to interactively specify arbitrary options, or whether we just want other scripts to be able to set specific, predetermined options. In the former case, it might make sense to have one env var per cargo command, which would allow precise control over which options are used where. In the latter case, it might be more sensible to have variables for specific options, and activate the options for the commands where they make sense if the corresponding variables are defined.
But I think we can address this separately, maybe when rewriting the check script in Rust. Since the sanitize feature is new, we won't break existing workflows, so I don't think it matters much that linting and sanitizing are not supported together for now. If we add support for it later, that wouldn't break things either, unless we change how env vars are used, but that would be a breaking change regardless, assuming anyone sets these variables.
When invoked with the `--sanitize` option, the `check.sh` script will run the checks with address and leak sanitation enabled. We already run similar checks in CI, so it's desirable to have them available locally as well. The `check` xtask also supports the `--sanitize` flag. The code is assembled from the deleted `jammy-asan.Dockerfile` and the `ubuntu-asan` job in `.github/workflows/test.yml`. The configuration in these two sources is not entirely consistent, so we should take care to find out which options we want to use. They should be the same locally and in CI. While we could resurrect a Dockerfile for running these checks, it adds significant overhead, while not providing much value, so I think integrating it into `check.sh` makes more sense.
7d63bc9 to
1a49002
Compare
When invoked with the
--sanitizeoption, thecheck.shscript willrun the checks with address and leak sanitation enabled. We already run
similar checks in CI, so it's desirable to have them available locally
as well. The
checkxtask also supports the--sanitizeflag.The code is assembled from the deleted
jammy-asan.Dockerfileand theubuntu-asanjob in.github/workflows/test.yml. The configuration inthese two sources is not entirely consistent, so we should take care to
find out which options we want to use. They should be the same locally
and in CI.
While we could resurrect a Dockerfile for running these checks, it adds
significant overhead, while not providing much value, so I think
integrating it into
check.shmakes more sense.TODO