Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WASI support #583

Merged
merged 23 commits into from
May 27, 2023
Merged

Add WASI support #583

merged 23 commits into from
May 27, 2023

Conversation

GregoryConrad
Copy link
Contributor

@GregoryConrad GregoryConrad commented May 21, 2023

Adds experimental WASI support. Requires nightly and file locking is currently a no-op, at least for the immediate future (needs to get implemented upstream).

Partially fixes #507

@GregoryConrad
Copy link
Contributor Author

GregoryConrad commented May 21, 2023

@cberner This is currently blocked by:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { kind: Unsupported, message: "operation not supported on this platform" }', src/tree_store/page_store/page_manager.rs:451:30

Which is:

        let mut storage = PagedCachedFile::new(
            file.try_clone().unwrap(), // panics on the unwrap()
            page_size as u64,
            read_cache_size_bytes,
            write_cache_size_bytes,
        )?;

Any ideas on what can be done to bypass this try_clone(), as it is not supported on WASI? I might be able to dig into the source of std later to see if it is possible to implement but that may be a long time from now since I am a bit busy

@cberner
Copy link
Owner

cberner commented May 21, 2023

I'm pretty sure it can just be removed: #584

I don't remember why I added that, but it looks like I refactored the code at some point and it's no longer necessary

@@ -22,18 +22,20 @@ libc = "0.2.104"
log = {version = "0.4.17", optional = true }
pyo3 = {version = "0.18.0", features=["extension-module", "abi3-py37"], optional = true }

[dev-dependencies]
[target.'cfg(not(target_os = "wasi"))'.dev-dependencies]
Copy link
Contributor Author

@GregoryConrad GregoryConrad May 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really hate this, but I don't think there is any other way to do benchmark specific dependencies (and you can't create a benching feature either because you can't have optional dev dependencies). If you have any ideas though, I am all ears.

(This divides test specific deps and benchmark specific deps, since essentially none of the benchmark deps compile to WASI)

// See also: https://github.com/WebAssembly/wasi-filesystem/issues/2

// Remove this line once wasi-libc has flock
#![cfg_attr(feature = "wasi", allow(unused_imports))]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This silences some unused import warnings that will go away once wasi-libc has flock

@GregoryConrad
Copy link
Contributor Author

GregoryConrad commented May 24, 2023

Currently running the wasi tests with:

cargo +nightly wasi test --features wasi -- --nocapture

Not sure how I'll be able to allow fs access with the above approach since simply adding --dir xyz doesn't work, but I'll cross that bridge when I get there.

For now, I'm getting

test db::test::crash_regression1 ... thread 'main' panicked at 'no filesystem on wasm', library/std/src/sys/wasi/os.rs:228:5

Guessing this is because of tempfile. Might see if I can patch in some dummy implementation that will work for WASI (i.e., hardcodes a tmp/ on WASI or something).

Edit: I was right; it originates from here

@GregoryConrad
Copy link
Contributor Author

I've started to get tests passing! 🥳🎉

To get useful test output, I've needed cargo-wasi; here's the command for that:

CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime --dir=." cargo +nightly wasi test --features=wasi -- --nocapture

To run tests without any extra dependencies, you can use this (but note this is near impossible to debug in case a test fails):

CARGO_TARGET_WASM32_WASI_RUNNER="wasmtime --dir=." cargo +nightly test --target wasm32-wasi --features=wasi

So I recommend we go with the cargo-wasi option for CI.

@GregoryConrad GregoryConrad marked this pull request as ready for review May 26, 2023 01:16
@GregoryConrad
Copy link
Contributor Author

@cberner Left some comments above that I would appreciate some feedback on. Other than that, this PR is ready to go as far as I can tell

Comment on lines +1 to +2
#[cfg(not(target_os = "wasi"))]
mod multithreading_test {
Copy link
Contributor Author

@GregoryConrad GregoryConrad May 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is the same as before (diff here isn't the clearest). Just wrapped it in a mod to avoid compiling/running any of it on WASI (no true support for multithreading atm)

@cberner
Copy link
Owner

cberner commented May 27, 2023

Overall this is looking much simpler than I had expected it to be!

@GregoryConrad
Copy link
Contributor Author

GregoryConrad commented May 27, 2023

In addition to the tempfile test changes I'll make at some point later today, I wanted to mention some warnings you get while compiling with nightly:

warning: variable does not need to be mutable
   --> src/tree_store/page_store/page_manager.rs:824:13
    |
824 |         let mut secondary = state.header.secondary_slot_mut();
    |             ----^^^^^^^^^
    |             |
    |             help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

warning: variable does not need to be mutable
   --> src/tree_store/page_store/page_manager.rs:880:13
    |
880 |         let mut secondary = state.header.secondary_slot_mut();
    |             ----^^^^^^^^^
    |             |
    |             help: remove this `mut`

   Compiling librocksdb-sys v0.11.0+8.1.1
warning: using `.borrow()` on a double reference, which returns `&<K as RedbValue>::SelfType<'_>` instead of borrowing the inner type
  --> src/table.rs:49:62
   |
49 |             .map(|x| x.map(|(key, _)| K::as_bytes(key.value().borrow()).as_ref().to_vec()));
   |                                                              ^^^^^^^^^
   |
   = note: `#[warn(suspicious_double_ref_op)]` on by default

warning: using `.borrow()` on a double reference, which returns `&<K as RedbValue>::SelfType<'_>` instead of borrowing the inner type
  --> src/table.rs:68:62
   |
68 |             .map(|x| x.map(|(key, _)| K::as_bytes(key.value().borrow()).as_ref().to_vec()));
   |                                                              ^^^^^^^^^

warning: using `.borrow()` on a double reference, which returns `&<K as RedbValue>::SelfType<'_>` instead of borrowing the inner type
   --> src/tree_store/btree.rs:270:55
    |
270 |             assert!(operation.safe_delete(entry?.key().borrow())?.is_some());
    |                                                       ^^^^^^^^^

warning: using `.borrow()` on a double reference, which returns `&<K as RedbValue>::SelfType<'_>` instead of borrowing the inner type
   --> src/tree_store/btree.rs:307:58
    |
307 |                 assert!(operation.safe_delete(entry.key().borrow())?.is_some());
    |                                                          ^^^^^^^^^

I'd be happy to fix these in a new PR since I imagine they will trickle down to stable eventually.

Edit: nevermind; I need to fix them in this PR because wasi ci is failing due to them

@GregoryConrad
Copy link
Contributor Author

GregoryConrad commented May 27, 2023

@cberner Instead of adding that create_tempfile back in, how would you feel about all tests using a tmp/ folder within the project root that can be created & cleaned up via just? Even with the create_tempfile function, WASI would still pollute the project root whenever tests are run (and would probably need this tmp/ anyways because of that). Further, with a local tmp/, you can also inspect failed tests' temp files in the future more easily.

@cberner
Copy link
Owner

cberner commented May 27, 2023

I don't think that's a good idea, because I want to support development workflows that do not use just. I do something similar in the benchmarks, where they create and try to cleanup their own tmpdir and it's kind of a mess. The only reason I do it there is that some OSs put /tmp in a tmpfs which messes up the benchmark timing.

What about reading the tmpdir from an environment variable? Would it be possible to create a directory in /tmp and then mount it via wasmtime --dir= in the justfile?

@GregoryConrad
Copy link
Contributor Author

Should be all set now. Non-wasi platforms will act the same way they did before, and just test_wasi will use the system's $TMPDIR.

@GregoryConrad GregoryConrad changed the title WASI support Add WASI support May 27, 2023
@GregoryConrad
Copy link
Contributor Author

GregoryConrad commented May 27, 2023

After this gets merged I can make 2 dummy commits to show the diffs that will be needed:

  • Once wasi-libc gets flock (and after that change is propagated to Rust's libc)
  • Once WASI no longer requires nightly

Just so those changes are less of a guessing game when the time comes. I'll link those two diffs in #507

@cberner cberner merged commit c54cebb into cberner:master May 27, 2023
@cberner
Copy link
Owner

cberner commented May 27, 2023

Merged. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

WASI support?
2 participants