Skip to content
New issue

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

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

Already on GitHub? # to your account

Getting stuck in infinite loop of the same events (OSX) #632

Closed
cs2dsb opened this issue Aug 20, 2018 · 5 comments
Closed

Getting stuck in infinite loop of the same events (OSX) #632

cs2dsb opened this issue Aug 20, 2018 · 5 comments

Comments

@cs2dsb
Copy link

cs2dsb commented Aug 20, 2018

I'm having a problem where poll_events or run_forever will start calling my callback with the same few events over and over.

I experience the issue even with the examples. I cloned this repo and ran the resizable example, pressed space a few times and it was ok but after 5 or so it started spewing out Resizable: true, Resizable: false as fast as the terminal could print.

I tried both stable and nightly rust:
stable-x86_64-apple-darwin unchanged - rustc 1.28.0 (9634041f0 2018-07-30)
nightly-x86_64-apple-darwin unchanged - rustc 1.30.0-nightly (33b923fd4 2018-08-18)

I'm running osx Sierra 10.12.6.

I had a look through existing issues and I don't think it's been reported before.

Any help much appreciated.

Thanks

@oeb25
Copy link

oeb25 commented Aug 21, 2018

I get this too on High Sierra 10.13.4 with minimal code. Spamming keys provokes this, but otherwise occurs after a few key presses normally.

Here's the code:

# Cargo.toml
[package]
name = "winit-bug"
version = "0.1.0"
authors = ["Oliver Bøving <oliverboving@gmail.com>"]

[dependencies]
winit = "0.17"
// main.rs
extern crate winit;

fn main() {
	let mut events_loop = winit::EventsLoop::new();
	let _window = winit::WindowBuilder::new().build(&events_loop).unwrap();

	loop {
		events_loop.poll_events(|e| {
			println!("{:?}", e);
		});
	}
}
# Cargo.lock extract
[metadata]
# ...
"checksum winit 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ba44cf306b981badc781894ab5d6fda54764a0512cbbf8db4685d329014143fa"

This is just a small extract or the events repeating when spamming A and D, saw something near 300k events in just about 5 seconds:

WindowEvent { window_id: WindowId(Id(140200705622512)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 2, state: Pressed, virtual_keycode: Some(D), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: ReceivedCharacter('d') }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 2, state: Pressed, virtual_keycode: Some(D), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: ReceivedCharacter('d') }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 0, state: Released, virtual_keycode: Some(A), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 0, state: Pressed, virtual_keycode: Some(A), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: ReceivedCharacter('a') }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 2, state: Released, virtual_keycode: Some(D), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }
WindowEvent { window_id: WindowId(Id(140200705622512)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 2, state: Pressed, virtual_keycode: Some(D), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, logo: false } } } }

If you need any help, testing or whatever, let me know!

@oeb25
Copy link

oeb25 commented Aug 21, 2018

Narrowed it down to call_user_callback_with_pending_events. Looks like the pending_queue gets refilled when it's depleted.

Putting some prints in the function like this,

fn call_user_callback_with_pending_events(&self) {
    println!("call_user_callback_with_pending_events start");
    loop {
        let pending_events_len = self.pending_events.lock().unwrap().len();

        println!("pending_events len {:?}", pending_events_len);

        let event = match self.pending_events.lock().unwrap().pop_front() {
            Some(event) => event,
            None => {
                println!("call_user_callback_with_pending_events end");
                return
            },
        };
        unsafe {
            self.user_callback.call_with_event(event);
        }
    }
}

I get this output,

pending events
call_user_callback_with_pending_events start
pending_events len 0
call_user_callback_with_pending_events end
done pending events
pending events
call_user_callback_with_pending_events start
pending_events len 2
pending_events len 1
pending_events len 0
pending_events len 7
pending_events len 6
pending_events len 5
pending_events len 4
pending_events len 3
pending_events len 2
pending_events len 1
pending_events len 0
pending_events len 7
pending_events len 6
pending_events len 5
pending_events len 4
pending_events len 3
pending_events len 2
pending_events len 1
pending_events len 0
pending_events len 7
pending_events len 6
pending_events len 5
pending_events len 4
pending_events len 3
pending_events len 2
pending_events len 1
pending_events len 0
pending_events len 7
pending_events len 6
pending_events len 5
pending_events len 4
pending_events len 3
pending_events len 2
pending_events len 1
pending_events len 0
pending_events len 7
pending_events len 6
pending_events len 5
pending_events len 4
pending_events len 3

My immediate thought, which I highly believe and strongly hope is false, is a bug in VecDeque.

I tried running self.pending_events.lock().unwrap().iter().cloned().collect::<Vec<_>>() at the start of the loop to see the contents for the queue. This unfortunately lead to the program halting at that statement.

I unfortunately do not have much experience with mutexes, which could be related, so I might be wrong.

I was using rustc 1.30.0-nightly (33b923fd4 2018-08-18) to get this error, I am unable to reproduce on rustc 1.27.0 (3eda71b00 2018-06-19). Is this related to the VecDeque vulnerability? Also found this pull request on rust and this issue, they might be related!

Hope this digging could help!

@anderejd
Copy link

anderejd commented Aug 21, 2018

I was using rustc 1.30.0-nightly (33b923fd4 2018-08-18) to get this error, I am unable to reproduce on rustc 1.27.0 (3eda71b00 2018-06-19).

If it is working on stable and not on nightly, you should report that to the Rust project https://github.com/rust-lang/rust

Please consider that Nightly is not suitable for any purpose other than developing future version of the compiler and the standard library.

@oeb25
Copy link

oeb25 commented Aug 21, 2018

@anderejd yes that is correct, I realize that now! Going into this I didn't test on other rust versions, which might be a good first starter 😉. If it is the case that this is related to the changes currently going on in nightly, and not in the hands of winit, this issue could be closed!

Further I believe it could be this as noted here on reddit.

Anyhow, had fun digging into this, even if it was for nothing 👍

@cs2dsb
Copy link
Author

cs2dsb commented Aug 22, 2018

I was using nightly after doing some embedded stuff. I thought I'd already tried stable but must have just run the previous build after switching toolchain... Whoops.

Thanks very much for the solution!

@cs2dsb cs2dsb closed this as completed Aug 22, 2018
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Development

No branches or pull requests

3 participants