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

terminal APIs not supported: can't call foreign function ioctl on OS linux #3719

Open
CramBL opened this issue Jun 28, 2024 · 3 comments
Open
Labels
A-shims Area: This affects the external function shims C-enhancement Category: a PR with an enhancement or an issue tracking an accepted enhancement

Comments

@CramBL
Copy link

CramBL commented Jun 28, 2024

I just learned about miri, and I'm trying to use it in a project and I cannot get it to run basically anything, I get errors in very basic "tests". e.g. this one.

#[cfg(test)]
mod tests {
    use crate::evaluate_compression::compression_result::color_grade_0_to_100_green_blue_white_yellow_red;
    use comfy_table::*;

    #[test]
    fn tune_color_grade_0_to_100_green_blue_white_yellow_red() {
        let mut table = Table::new();
        let mut cells = vec![];
        for x in 0..=100 {
            let c =
                comfy_table::Cell::new(x).fg(color_grade_0_to_100_green_blue_white_yellow_red(x));
            cells.push(c);

            if cells.len() == 26 {
                table.add_row(cells);
                cells = vec![];
            }
        }
        table.add_row(cells);
        println!("{table}");
    }
}

The color_grade_0_to_100_green_blue_white_yellow_red function looks like below (bad code 🤡 )

pub fn color_grade_0_to_100_green_blue_white_yellow_red(val: u8) -> comfy_table::Color {
    debug_assert!(val <= 100);

    if val <= 50 {
        // Transition from green to cyan to blue to white at 50%
        let (r, g, b) = match val {
            0..=34 => {
                // Green to Cyan
                let r = 0;
                let g = 255;
                let b = (val as f32 * 6.2) as u8; // 0 to 255
                (r, g, b)
            }
            35..=50 => {
                // Cyan to Blue to White
                let r = ((val - 25) as f32 * 10.2) as u8; // 0 to 255
                let g = 255;
                let b = 255;
                (r, g, b)
            }
            _ => unreachable!(),
        };
        comfy_table::Color::Rgb { r, g, b }
    } else if val <= 80 {
        // Transition from white at 50% to yellow at 80%
        let r = 255;
        let g = 255;
        let b = 255 - ((val - 50) as f32 * 8.5) as u8; // 255 to 0
        comfy_table::Color::Rgb { r, g, b }
    } else {
        // Transition from yellow at 80% to red at 100%
        let r = 255;
        let g = 255 - ((val - 80) as f32 * 12.75) as u8; // 255 to 0
        let b = 0;
        comfy_table::Color::Rgb { r, g, b }
    }
}

And I get this result from MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-backtrace=full" cargo +nightly miri test tune_color_grade.

MIRIFLAGS="-Zmiri-disable-isolation -Zmiri-backtrace=full" cargo +nightly miri test tune_color_grade
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.06s
     Running unittests src/main.rs (target/miri/x86_64-unknown-linux-gnu/debug/deps/qft-e789802002b6f8c2)

running 1 test
test evaluate_compression::compression_result::tests::tune_color_grade_0_to_100_green_blue_white_yellow_red ... error: unsupported operation: can't call foreign function `ioctl` on OS `linux`
   --> /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossterm-0.27.0/src/terminal/sys/unix.rs:55:34
    |
55  |     if wrap_with_result(unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut size) }).is_ok() {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function `ioctl` on OS `linux`
    |
    = help: if this is a basic API commonly used on this target, please report an issue with Miri
    = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases
    = note: BACKTRACE on thread `evaluate_compre`:
    = note: inside `crossterm::terminal::sys::unix::window_size` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossterm-0.27.0/src/terminal/sys/unix.rs:55:34: 55:73
    = note: inside `crossterm::terminal::sys::unix::size` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossterm-0.27.0/src/terminal/sys/unix.rs:64:30: 64:43
    = note: inside `crossterm::terminal::size` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossterm-0.27.0/src/terminal.rs:137:5: 137:16
    = note: inside `comfy_table::Table::width` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/comfy-table-7.1.1/src/table.rs:274:37: 274:53
    = note: inside `comfy_table::utils::arrangement::arrange_content` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/comfy-table-7.1.1/src/utils/arrangement/mod.rs:17:23: 17:36
    = note: inside `comfy_table::utils::build_table` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/comfy-table-7.1.1/src/utils/mod.rs:51:24: 51:46
    = note: inside `comfy_table::Table::lines` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/comfy-table-7.1.1/src/table.rs:95:9: 95:26
    = note: inside `<comfy_table::Table as std::fmt::Display>::fmt` at /home/marcbk/.cargo/registry/src/index.crates.io-6f17d22bba15001f/comfy-table-7.1.1/src/table.rs:47:25: 47:37
    = note: inside `core::fmt::rt::Argument::<'_>::fmt` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/rt.rs:165:63: 165:82
    = note: inside `std::fmt::write` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/mod.rs:1168:21: 1168:44
    = note: inside `<std::vec::Vec<u8> as std::io::Write>::write_fmt` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/mod.rs:1835:15: 1835:43
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1129:25: 1129:84
    = note: inside `std::option::Option::<std::sync::Arc<std::sync::Mutex<std::vec::Vec<u8>>>>::map::<(), {closure@std::io::stdio::print_to_buffer_if_capture_used::{closure#0}::{closure#0}}>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:1103:29: 1103:33
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1128:13: 1131:15
    = note: inside `std::thread::LocalKey::<std::cell::Cell<std::option::Option<std::sync::Arc<std::sync::Mutex<std::vec::Vec<u8>>>>>>::try_with::<{closure@std::io::stdio::print_to_buffer_if_capture_used::{closure#0}}, std::option::Option<()>>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/local.rs:283:12: 283:27
    = note: inside `std::io::stdio::print_to_buffer_if_capture_used` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1124:12: 1132:11
    = note: inside `std::io::stdio::print_to::<std::io::Stdout>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1112:8: 1112:45
    = note: inside `std::io::_print` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/io/stdio.rs:1227:5: 1227:37
note: inside `evaluate_compression::compression_result::tests::tune_color_grade_0_to_100_green_blue_white_yellow_red`
   --> src/evaluate_compression/compression_result.rs:432:9
    |
432 |         println!("{table}");
    |         ^^^^^^^^^^^^^^^^^^^
note: inside closure
   --> src/evaluate_compression/compression_result.rs:418:63
    |
417 |     #[test]
    |     ------- in this procedural macro expansion
418 |     fn tune_color_grade_0_to_100_green_blue_white_yellow_red() {
    |                                                               ^
    = note: inside `<{closure@src/evaluate_compression/compression_result.rs:418:5: 433:6} as std::ops::FnOnce<()>>::call_once - shim` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
    = note: inside `<fn() -> std::result::Result<(), std::string::String> as std::ops::FnOnce<()>>::call_once - shim(fn() -> std::result::Result<(), std::string::String>)` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
    = note: inside `test::__rust_begin_short_backtrace::<std::result::Result<(), std::string::String>, fn() -> std::result::Result<(), std::string::String>>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:625:18: 625:21
    = note: inside `test::types::RunnableTest::run` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/types.rs:146:40: 146:71
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:648:60: 648:79
    = note: inside `<std::panic::AssertUnwindSafe<{closure@test::run_test_in_process::{closure#0}}> as std::ops::FnOnce<()>>::call_once` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:272:9: 272:19
    = note: inside `std::panicking::r#try::do_call::<std::panic::AssertUnwindSafe<{closure@test::run_test_in_process::{closure#0}}>, std::result::Result<(), std::string::String>>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:553:40: 553:43
    = note: inside `std::panicking::r#try::<std::result::Result<(), std::string::String>, std::panic::AssertUnwindSafe<{closure@test::run_test_in_process::{closure#0}}>>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:517:19: 517:88
    = note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<{closure@test::run_test_in_process::{closure#0}}>, std::result::Result<(), std::string::String>>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:350:14: 350:33
    = note: inside `test::run_test_in_process` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:648:27: 648:81
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:569:43: 577:18
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/test/src/lib.rs:599:41: 599:83
    = note: inside `std::sys::backtrace::__rust_begin_short_backtrace::<{closure@test::run_test::{closure#1}}, ()>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:155:18: 155:21
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:542:17: 542:71
    = note: inside `<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@test::run_test::{closure#1}}, ()>::{closure#2}::{closure#0}}> as std::ops::FnOnce<()>>::call_once` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:272:9: 272:19
    = note: inside `std::panicking::r#try::do_call::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@test::run_test::{closure#1}}, ()>::{closure#2}::{closure#0}}>, ()>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:553:40: 553:43
    = note: inside `std::panicking::r#try::<(), std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@test::run_test::{closure#1}}, ()>::{closure#2}::{closure#0}}>>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:517:19: 517:88
    = note: inside `std::panic::catch_unwind::<std::panic::AssertUnwindSafe<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@test::run_test::{closure#1}}, ()>::{closure#2}::{closure#0}}>, ()>` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:350:14: 350:33
    = note: inside closure at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/mod.rs:541:30: 543:16
    = note: inside `<{closure@std::thread::Builder::spawn_unchecked_<'_, '_, {closure@test::run_test::{closure#1}}, ()>::{closure#2}} as std::ops::FnOnce<()>>::call_once - shim(vtable)` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5: 250:71
    = note: inside `<std::boxed::Box<dyn std::ops::FnOnce()> as std::ops::FnOnce<()>>::call_once` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2064:9: 2064:52
    = note: inside `<std::boxed::Box<std::boxed::Box<dyn std::ops::FnOnce()>> as std::ops::FnOnce<()>>::call_once` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2064:9: 2064:52
    = note: inside `std::sys::pal::unix::thread::Thread::new::thread_start` at /home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread.rs:108:17: 108:64
    = note: this error originates in the macro `println` which comes from the expansion of the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

error: test failed, to rerun pass `--bin qft`

Caused by:
  process didn't exit successfully: `/home/marcbk/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner /home/marcbk/repos/quick-file-transfer/target/miri/x86_64-unknown-linux-gnu/debug/deps/qft-e789802002b6f8c2 tune_color_grade` (exit status: 1)
note: test exited abnormally; to see the full output pass --nocapture to the harness.

I was not expect all these issues since I run this project with cargo hack test --feature-powerset on linux/windows/macos with no issues.

I must be doing something wrong?

@cgettys-microsoft
Copy link
Contributor

Pretty sure this duplicates #743.

There are a lot of syscalls, and a lot of platforms.
E.g. Linux alone has something like 500:
a list.
And a lot of sys calls have many, many flags and options.

Not all syscalls are emulated / supported by Miri yet. Even when a sys call is supported in part, that doesn't mean every combination of flags / arguments is implemented either.
Keep in mind Miri tries to emulate sys calls for all host architectures, it doesn't assume the host is the same OS or architecture.
Also keep in mind that Miri is not just blindly passing the data through - it is checking for UB and API misuse, including in the arguments to syscalls.

I don't want to put words in the maintainers' mouths, but from what I've personally seen, they are friendly and welcome contributions :).

@saethlin
Copy link
Member

Someone should look into whether it's reasonable to shim all libc APIs for implementing a TUI. There are a handful beyond this one ioctl. For example, being able to get the current window size is unlikely to be useful without being able to put the terminal into raw mode.

It's not clear to me if these APIs can be implemented portably.

@cgettys-microsoft
Copy link
Contributor

Yeah, I'm not sure these can be done portably either. Not sure what the Miri stance is on non-portable syscalls - to me, that seems like a second dimension beyond the "basic" isolation (i.e. some stuff like basic file system stuff breaks isolation, but may still be portable / emulatable).

@RalfJung RalfJung changed the title Surprising error on PopOS 22.04: can't call foreign function ioctl on OS linux terminal APIs not supported: can't call foreign function ioctl on OS linux Jun 29, 2024
@RalfJung RalfJung added C-enhancement Category: a PR with an enhancement or an issue tracking an accepted enhancement A-shims Area: This affects the external function shims labels Jul 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-shims Area: This affects the external function shims C-enhancement Category: a PR with an enhancement or an issue tracking an accepted enhancement
Projects
None yet
Development

No branches or pull requests

4 participants