valpackett / evscript

A tiny sandboxed Dyon scripting environment for evdev input devices that lets you do e.g. xcape in Wayland | now on https://codeberg.org/valpackett/evscript
https://codeberg.org/valpackett/evscript
The Unlicense
121 stars 7 forks source link

thread 'main' panicked at 'ioctl: Sys(EINVAL)' #3

Closed kevinmost closed 6 years ago

kevinmost commented 6 years ago

Hi! Not sure if I'm doing something wrong here, as I'm not too versed in ioctl in general.

I built evscript and installed it using the instructions in the README in this repo, but running it seems to give me a panic. I'm using the stock xcape-like config that was provided in the README as well.

% cat ~/better_xcape.dyon 
//! [events]
//! keys = ['ESC', 'LEFTSHIFT', '9', '0']
fn main() ~ evdevs, uinput {
    should_esc := false
    should_lshift := false
    should_rshift := false
    loop {
        evts := next_events(evdevs)
        for i len(evts) {
            evt := evts[i]
            xcape(mut should_esc, evt, KEY_CAPSLOCK(), [KEY_ESC()])
            xcape(mut should_lshift, evt, KEY_LEFTSHIFT(), [KEY_LEFTSHIFT(), KEY_9()])
            xcape(mut should_rshift, evt, KEY_RIGHTSHIFT(), [KEY_LEFTSHIFT(), KEY_0()])
        }
    }
}

% RUST_BACKTRACE=1 evscript -f ~/better_xcape.dyon -d /dev/input/event3
thread 'main' panicked at 'ioctl: Sys(EINVAL)', src/libcore/result.rs:916:5
stack backtrace:
   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: <unknown>
  10: <unknown>
  11: <unknown>
  12: <unknown>
  13: <unknown>
  14: <unknown>
  15: <unknown>
  16: __libc_start_main
  17: <unknown>

Would love to contribute but I'm not sure where to start trying to diagnose this. I see that EINVAL means that one of the parameters to the ioctl function was invalid but I'm not sure where to go from there.

valpackett commented 6 years ago

Hi. A backtrace full of <unknown> is not very helpful :) Try building without --release (the binary will be in target/debug/evscript)

kevinmost commented 6 years ago

Thanks for the super-fast reply. Ah, I had no idea how I was supposed to get a useful backtrace, but that makes sense that I'd need to run a non-release version.

% RUST_BACKTRACE=1 ./evscript -f ~/better_xcape.dyon -d /dev/input/event3
thread 'main' panicked at 'evdev open(): Sys(EACCES)', src/libcore/result.rs:916:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::_print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::begin_panic
   6: std::panicking::begin_panic_fmt
   7: rust_begin_unwind
   8: core::panicking::panic_fmt
   9: core::result::unwrap_failed
             at /build/rust/src/rustc-1.24.0-src/src/libcore/macros.rs:23
  10: <core::result::Result<T, E>>::expect
             at /build/rust/src/rustc-1.24.0-src/src/libcore/result.rs:809
  11: evscript::main::{{closure}}::{{closure}}
             at src/main.rs:255
  12: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &'a mut F>::call_once
             at /build/rust/src/rustc-1.24.0-src/src/libcore/ops/function.rs:271
  13: <core::option::Option<T>>::map
             at /build/rust/src/rustc-1.24.0-src/src/libcore/option.rs:404
  14: <core::iter::Map<I, F> as core::iter::iterator::Iterator>::next
             at /build/rust/src/rustc-1.24.0-src/src/libcore/iter/mod.rs:1251
  15: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::from_iter
             at /build/rust/src/rustc-1.24.0-src/src/liballoc/vec.rs:1801
  16: <alloc::vec::Vec<T> as core::iter::traits::FromIterator<T>>::from_iter
             at /build/rust/src/rustc-1.24.0-src/src/liballoc/vec.rs:1713
  17: core::iter::iterator::Iterator::collect
             at /build/rust/src/rustc-1.24.0-src/src/libcore/iter/iterator.rs:1298
  18: evscript::main::{{closure}}
             at src/main.rs:255
  19: <core::option::Option<T>>::map
             at /build/rust/src/rustc-1.24.0-src/src/libcore/option.rs:404
  20: evscript::main
             at src/main.rs:252
  21: std::rt::lang_start::{{closure}}
             at /build/rust/src/rustc-1.24.0-src/src/libstd/rt.rs:74
  22: std::panicking::try::do_call
  23: __rust_maybe_catch_panic
  24: std::rt::lang_start_internal
  25: std::rt::lang_start
             at /build/rust/src/rustc-1.24.0-src/src/libstd/rt.rs:74
  26: main
  27: __libc_start_main
  28: _start
valpackett commented 6 years ago

hmm, line 255 is opening the device (/dev/input/event3 that is, not uinput). Do you have permissions on the device? Try running as root. (I'd expect EACCES not EINVAL, but what else could it be…)

valpackett commented 6 years ago

err, it is evdev open(): Sys(EACCES) in the second stacktrace, but the original one was EINVAL o_0

kevinmost commented 6 years ago

Yeah, it's behaving unusually. Do you think it's a permissions issue? I'm not doing anything unusual AFAICT, I'm on near-stock Antergos and haven't touched any permissions in /dev/*.

So running as my user gives me EACCES as far as I can tell:

% RUST_BACKTRACE=1 /home/kmost/evscript/target/debug/evscript -f /home/kmost/better_xcape.dyon -d /dev/input/event3
thread 'main' panicked at 'evdev open(): Sys(EACCES)', src/libcore/result.rs:916:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::_print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::begin_panic
   6: std::panicking::begin_panic_fmt
   7: rust_begin_unwind
   8: core::panicking::panic_fmt
   9: core::result::unwrap_failed
             at /build/rust/src/rustc-1.24.0-src/src/libcore/macros.rs:23
  10: <core::result::Result<T, E>>::expect
             at /build/rust/src/rustc-1.24.0-src/src/libcore/result.rs:809
  11: evscript::main::{{closure}}::{{closure}}
             at src/main.rs:255
  12: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &'a mut F>::call_once
             at /build/rust/src/rustc-1.24.0-src/src/libcore/ops/function.rs:271
  13: <core::option::Option<T>>::map
             at /build/rust/src/rustc-1.24.0-src/src/libcore/option.rs:404
  14: <core::iter::Map<I, F> as core::iter::iterator::Iterator>::next
             at /build/rust/src/rustc-1.24.0-src/src/libcore/iter/mod.rs:1251
  15: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T, I>>::from_iter
             at /build/rust/src/rustc-1.24.0-src/src/liballoc/vec.rs:1801
  16: <alloc::vec::Vec<T> as core::iter::traits::FromIterator<T>>::from_iter
             at /build/rust/src/rustc-1.24.0-src/src/liballoc/vec.rs:1713
  17: core::iter::iterator::Iterator::collect
             at /build/rust/src/rustc-1.24.0-src/src/libcore/iter/iterator.rs:1298
  18: evscript::main::{{closure}}
             at src/main.rs:255
  19: <core::option::Option<T>>::map
             at /build/rust/src/rustc-1.24.0-src/src/libcore/option.rs:404
  20: evscript::main
             at src/main.rs:252
  21: std::rt::lang_start::{{closure}}
             at /build/rust/src/rustc-1.24.0-src/src/libstd/rt.rs:74
  22: std::panicking::try::do_call
  23: __rust_maybe_catch_panic
  24: std::rt::lang_start_internal
  25: std::rt::lang_start
             at /build/rust/src/rustc-1.24.0-src/src/libstd/rt.rs:74
  26: main
  27: __libc_start_main
  28: _start

, but running the same command as root gives me EINVAL. And for some reason, the backtrace is filled with <unknown>. Not too familiar with Rust either, to be honest, so I'm not sure why that would happen:

# RUST_BACKTRACE=1 /home/kmost/evscript/target/debug/evscript -f /home/kmost/better_xcape.dyon -d /dev/input/event3
thread 'main' panicked at 'ioctl: Sys(EINVAL)', src/libcore/result.rs:916:5
stack backtrace:
   0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: <unknown>
  10: <unknown>
  11: <unknown>
  12: <unknown>
  13: <unknown>
  14: <unknown>
  15: <unknown>
  16: <unknown>
  17: <unknown>
  18: __libc_start_main
  19: <unknown>
valpackett commented 6 years ago

hmm I can reproduce the exact same behavior on my Arch VM (including the unknown backtrace). I can see the backtrace in lldb though. It's ui_set_evbit.

Looks like the ioctl numbers are wrong for Linux, I'll fix that

kevinmost commented 6 years ago

Awesome! Looking forward to a fix. Thanks for the quick replies. :)

valpackett commented 6 years ago

Try now (14f4aa8e4f096b7b836fbe1a9e7d285891b43661)

kevinmost commented 6 years ago

Works now when I run as root! :tada:

There's one error that gets emitted when using your sample dyon config:

 --- ERROR --- 
In `/home/kmost/better_xcape.dyon`:

Type mismatch (#200):
Expected `[]`, found `{}`
9,19:         for i len(evts) {
9,19:                   ^

I'm not familiar with dyon syntax either, but it seems to be working fine despite that syntax error.

One thing I'm noticing is a slight delay when pressing a button multiple times (eg, if you mash left-shift a few times, it takes a little while for all of the left parens to be inputted), but it looks like xcape has a similar delay on escape, so this might just be a hardware or an OS-level limitation?

valpackett commented 6 years ago

Yes, this is fine, I get that error all the time, just ignore it.

Mashing shifts works instantly on my machine (in Weston). There are no additional delays, as soon as evscript receives the press event followed by the release event (without being interrupted by a repeat event), it presses the specified key.

kevinmost commented 6 years ago

Yeah, I figured, since I don't think I've seen xcape lag on other devices I've used either. I'll chalk it up to a hardware limitation!

valpackett commented 6 years ago

You can use evemu to read events from that keyboard, see what's happening.