|
[A5.0.10] Critical Issue with Keyboard Locking Up Due to Joystick Event Handling |
Kris Asick
Member #1,424
July 2001
|
I know I'm barely around here anymore, but this one's a serious problem and after MANY hours of testing, I've traced the problem to Allegro itself, possibly a result of my hardware configuration and how I'm using Allegro so I've included those details: I'm running Allegro 5.0.10, compiling through MSVC2010, forcing the usage of OpenGL, running Windows 8.1 Pro, 16 GB RAM, 200 GB of HD space free, 4 GHz CPU and a GeForce GTX 660 video card. The Problem, In Short: If you create an event buffer for joysticks, but continue to press keyboard keys, sooner or later, the keyboard state completely freezes... SYSTEM-WIDE! :O The Problem, In Long: So here's the situation: I've created a unified controls system for my current and future projects built on top of Allegro, the goal of which being to simplify all control input so that I simply set which interfaces access which controls, then when writing game code, instead of referencing specific keys or joystick functions, I simply reference the control and how I want to read it, either as a boolean, a floating point value, buffered, one-shot, etc. Up until now, the system's been flawless. Even after instigating joystick support it's worked perfectly. Then I went back to using keyboard controls as I started getting some more work done with an editor I built for the project I'm working on and suddenly at one moment, my keyboard keys froze up. Nothing I was pushing was doing anything. So I went into the debugger to try and track the problem down. I spent a solid 10 minutes scouting variables and tracing program flow but nothing seemed out of the ordinary... until I tried to type something into the debugger and nothing happened! At this point I realized the keyboard state was frozen for everything, not just my program. I tried unplugging my keyboard and plugging it back in. This unfroze the keyboard for everything, including my own project. I continued doing my editor work and it happened again... and eventually again. I thought maybe my keyboard was broken so I stopped work on my stuff for a number of hours and did other tasks and ran into no issues. I've spent the past couple hours carefully enabling and disabling tiny fragments of my code and ultimately discovered that so long as I don't create an ALLEGRO_EVENT_QUEUE and attach the joystick event source to it, nothing goes wrong with the keyboard. Having the joystick and keyboard going together creates no issues so long as there's no joystick queue. I've also discovered that you actually have to press keys for anything to go wrong. I tried running my program with all the event queues doing their things and just leaving it sit doing nothing for twice as long as it was taking for my keyboard to freeze up, then going back to it and finding the keyboard still functioning. Also, when the freeze occurs, not only do joysticks continue to function properly, along with joystick events, but non-standard keyboard controls continue to function, such as media keys, volume sliders, gaming keys, etc. The only keys frozen are the actual keys Allegro would normally read. As a work-around to this, since my project could very well be ready for commercial launch in only a matter of months, I'm just going to disable the joystick event handling internally to my program and instead of allowing immediate hot-swapping of joysticks, I'm going to have a button in my controls configuration menu to refresh all detected joysticks, since you don't need an event queue to read the joystick states, nor do you need it to reconfigure joysticks, it's just a lot more convenient to automatically detect if joysticks need to be reconfigured with ALLEGRO_EVENT_JOYSTICK_CONFIGURATION. With over 12,000 lines of code in place for my project thus-far (over 50% ready for initial public release) it would be difficult to post chunks of code but really, the entire problem can be traced to this single line of code, which is only called once and either seconds or minutes prior to the problem occurring: al_register_event_source(_joyevents,al_get_joystick_event_source()); I know you guys might be thinking my event handler might have something wrong with it, but even if I completely comment it out and flush the event queue every frame so that it doesn't get jammed up, the problem still occurs. If there's any additional testing you guys want me to try, let me know. All you need to do to recreate the same circumstances leading to this problem is:
--- Kris Asick (Gemini) |
Thomas Fjellstrom
Member #476
June 2000
|
Kris Asick said: I know you guys might be thinking my event handler might have something wrong with it, but even if I completely comment it out and flush the event queue every frame so that it doesn't get jammed up, the problem still occurs. That is of course the first thing I thought of. But actually reading that the entire system's keyboard locks up, thats... Interesting... I can't really explain that. Maybe somehow we're letting events get queued up in the OS itself and the buffers all fill? I have no idea. None of it makes any sense to me. Is it possible to try out the latest 5.1 (not suggesting you completely switch to it) and see if it happens there? -- |
Kris Asick
Member #1,424
July 2001
|
Thomas Fjellstrom said: Is it possible to try out the latest 5.1 (not suggesting you completely switch to it) and see if it happens there? Possibly, though the last time I tried to build Allegro from source was a long while back on a completely different computer, thus I forget what's involved in doing it. There are binaries available on the Allegro website for the 5.1.x branch, but they're for MSVC2013 and I'm using MSVC2010. ...going to bed in a moment; I'll take a look into this later tonight after I'm up again. In the interim, any quick links for info on how to build the 5.1.x branch with MSVC2010? --- Kris Asick (Gemini) |
Elias
Member #358
May 2000
|
How are you handling the events if you have two queues? Since Allegro has no way to wait for two queues at once, won't one of the queues always overflow while you're waiting for the other? Not sure this is the problem, but I think all examples use a single queue so this seems to be one out of the ordinary thing you're doing. Maybe we should add a function which can wait for multiple queues. And it's of course still a bug that an overflown queue would lock up the keyboard completely. -- |
Kris Asick
Member #1,424
July 2001
|
There's no queue waiting in my program. While I have multiple queues, (display, keyboard and joystick), each only gets scanned and subsequently emptied once per program loop. The way my program is coded, if an event queue became unable to be emptied, the program itself would hang. This never happens. Each event queue is scanned once per game loop with code like this: while (al_get_next_event(displayevents,&al_event)) switch (al_event.type) { case ALLEGRO_EVENT_DISPLAY_SWITCH_IN: { GCtrl_SwitchIn(); break; } case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT: { GCtrl_SwitchOut(); break; } } I should also point out, when the keyboard stops working, the keyboard event queue is EMPTY. Same with the joystick queue. Same with the display queue. ------------- EDIT: Geeze... getting Allegro to build is a trip and a half... First I had to deal with CMake getting flagged by Avast as a virus, then I had to deal with discrepancies between the installation guide and what was actually supposed to be input (the tutorial says to install A5 stuff to "C:\devel" but it's actually supposed to be "C:\dev"), and now gcc.exe isn't being found while trying to get the dependencies compiled despite the path variable being correct and despite having MinGW installed, all because the CMake stuff wants to use gcc.exe from "C:/MinGW/mingw32/bin" as opposed to "C:/MinGW/bin" where MinGW actually put the file. Getting there... ------------- EDIT: ...and... now I'm officially stuck. C:\MinGW\bin\ld.exe is telling me that it can't find "crt2.o" even though it's right there in C:\MinGW\lib. Path variables are set up and I even added that exact directory to the path (on top of the directories I already added from the Getting Started guide) and even tried rebooting and... nope. Starting to remember why I always gave up and went back to pre-compiled binaries in the past with A4... ------------- Yet Another Edit: OK, so the problem has nothing to do with event handling. I managed to get the problem to occur with no joystick event handling present. That's when it occurred to me that it MIGHT be compiler optimization related... I already had to disable "Whole Program Optimization" because of the way my code was working, but so far, testing with all optimizations disabled is producing no issues. I'll continue testing to see which optimization is specifically causing the issue, if that is indeed the problem. I didn't run into any issues at all though until I added in joystick support, so clearly something the joystick support in A5 is doing is not compatible with one of the compiler optimizations I'm using. I'll figure it out and get back to you guys. ------------- EDIT: After nearly breaking my fingers off from testing the crud out of this by pressing numerous keyboard keys at the freaking speed of light for minutes on end, I've determined that the ONLY way to prevent this issue from happening is to either: 1. NEVER call al_install_joystick() OR 2. Completely disable ALL compiler optimizations Virtually ANY compiler optimization will cause this problem to occur. I tried groups of optimizations, individual optimizations, and no matter what, the only time the problem never occurred with joystick support going was when all optimizations were disabled. Granted, the only two optimizations I know for sure caused issues were "Inline Function Expansion" and the general "Optimization" setting which is set between Minimize Size, Maximize Speed and Full Optimization. ...if memory serves, isn't there a way to disable optimizations for specific sections of code? I wonder if maybe disabling optimizations only for my unified controls framework would actually be enough... or maybe just disabling optimizations around joystick-specific parts... I'm going to go look into if this is possible and report back if I figure out anything more, since disabling ALL compiler optimizations is not a very nice solution... --- Kris Asick (Gemini) |
Thomas Fjellstrom
Member #476
June 2000
|
One last random guess from me. How many systems does this happen on? And how many allegro 5 programs? -- |
Kris Asick
Member #1,424
July 2001
|
The random nature of this problem is really bugging me. I spent HOURS testing all of that to discover that optimizations seemed to be the issue... then in order to get some work done I compiled with optimizations completely disabled and the problem happened within 3 minutes. It still seems to be very much related to the joystick support. So long as I comment out al_install_joystick(), the keyboard works fine forever and given that many hours of testing has already gone into this project since making its universal editor and completing the first of the initial three games which will be released for it, I'm extremely certain my keyboard handler is working properly. I won't have a chance to try this with other computers for a few days yet. Due to extremely stupid things which went down at the start of the year I don't have access to most of my computers at the moment save for my primary Windows 8.1 system and my 100 MHz Windows 98 laptop which will not suffice for an A5 program. Dad has a Windows 7 desktop and a Vista laptop. He probably won't be around on Thursday and I'll be able to try my code on his systems then and see if the same problems occur. What would be some good A5 programs to test which will still run keyboard support while joystick support is active? --- Kris Asick (Gemini) |
Mark Oates
Member #1,146
March 2001
|
That's so bizarre. Do you have a bare minimum example program that will recreate the anomaly? I had a similar issue a while back on my framework, involving something-er-rather not working as expected. It had something to do with ALLEGRO_OPENGL not rendering al_scaled_bitmap and all the al_draw_bitmap functions that were only scale-and-rotation variants. I was convinced it was a problem with the underlying allegro system, since it only occurred on ALLEGRO_OPENGL and all of my other code was completely agnostic. After months, I eventually found the error was related to my code. I can't remember what it was exactly now, but your post reminds me very much of that scenario. But, I just remember the one thing that finally broke the ice for me during those months was a bare-bones program that, oddly, didn't reproduce the anomaly. -- |
Kris Asick
Member #1,424
July 2001
|
Well, I don't have a bare-bones program on hand, and while I COULD provide you guys with my unified controls framework, it would be difficult to use without understanding what exactly it does. However, I described the most basic program possible at the start of this thread which should reproduce the issue I'm running into. My actual interfacing with Allegro is very minimal with my control system. This is the code for initializing keyboard and joystick support: 1 if (al_install_keyboard())
2 {
3 keyboard_enabled = true; keyboard_available = true;
4 al_get_keyboard_state(&_keystate);
5 memcpy(&_prev_keystate,&_keystate,sizeof(ALLEGRO_KEYBOARD_STATE));
6 if ((_keybuffer = al_create_event_queue()) == NULL) return 2;
7 al_register_event_source(_keybuffer,al_get_keyboard_event_source());
8 }
9 else
10 keyboard_enabled = false;
11
12 if (al_install_joystick())
13 {
14 joystick_enabled = true; joystick_available = true;
15 GCtrl_ReconfigureJoysticks();
16 if ((_joyevents = al_create_event_queue()) == NULL) return 2;
17 al_register_event_source(_joyevents,al_get_joystick_event_source());
18 }
19 else
20 joystick_enabled = false;
This is the code for GCtrl_ReconfigureJoysticks(): void GCtrl_ReconfigureJoysticks (void) { int z; al_reconfigure_joysticks(); for (z = 0; z < 4; z++) { _joystick[z] = al_get_joystick(z); if (_joystick[z] != NULL) { al_get_joystick_state(_joystick[z],&_joystate[z]); memcpy(&_prev_joystate[z],&_joystate[z],sizeof(ALLEGRO_JOYSTICK_STATE)); } } } While the actual keyboard and joystick interfacing which occurs once per game loop is: 1 if (keyboard_enabled)
2 {
3 memcpy(&_prev_keystate,&_keystate,sizeof(ALLEGRO_KEYBOARD_STATE));
4 al_get_keyboard_state(&_keystate);
5 if (!typing_enabled) GCtrl_ClearKeyboardBuffer();
6 }
7 if (joystick_enabled)
8 {
9 for (z = 0; z < 4; z++) if (_joystick[z] != NULL)
10 {
11 memcpy(&_prev_joystate[z],&_joystate[z],sizeof(ALLEGRO_JOYSTICK_STATE));
12 al_get_joystick_state(_joystick[z],&_joystate[z]);
13 }
14 while (al_get_next_event(_joyevents,&joyevent)) switch (joyevent.type)
15 {
16 case ALLEGRO_EVENT_JOYSTICK_CONFIGURATION: GCtrl_ReconfigureJoysticks(); break;
17 }
18 }
A couple more routines related to this are: 1void GCtrl_ClearKeyboardBuffer (void)
2{
3 while (al_drop_next_event(_keybuffer)) {}
4}
5
6bool GCtrl_GetNextKeyInBuffer (int *unicode, int *keycode)
7{
8 ALLEGRO_EVENT keyevent;
9 while (al_get_next_event(_keybuffer,&keyevent))
10 {
11 if (keyevent.type == ALLEGRO_EVENT_KEY_CHAR)
12 {
13 if (unicode != NULL) *unicode = keyevent.keyboard.unichar;
14 if (keycode != NULL) *keycode = keyevent.keyboard.keycode;
15 return true;
16 }
17 }
18 return false;
19}
Everything else, save for a few calls to al_key_down(), al_get_joystick_num_sticks(), al_get_joystick_num_axes() and al_get_joystick_num_buttons(), is code which doesn't interact with Allegro or the system in general and thus should be incapable of completely freezing the state of the keyboard for the entire computer, not just my own program. Although I should point out too that these calls only get made when controls have been defined which use them. So far, since I've been using my universal editor to test all of this, which doesn't have any joystick controls assigned, the al_get_joystick_num_ commands never get called. When I have a free moment, I'll try to whip together a bare-bones program, but it may take awhile; I barely have time to work on code as it is. EDIT: *takes a second look at the definition of ALLEGRO_JOYSTICK_STATE* .......................waitaminute... EDIT (again): Nevermind... The manual makes it look as though the size of ALLEGRO_JOYSTICK_STATE may be variable, but looking at the Allegro source it's fixed to certain maximum values. --- Kris Asick (Gemini) |
Thomas Fjellstrom
Member #476
June 2000
|
What we're suggesting is you make your own bare bones program. Forget about your framework, just use allegro. Either start from a wiki example, an allegro example, or from scratch. -- |
Kris Asick
Member #1,424
July 2001
|
Thomas Fjellstrom said: What we're suggesting is you make your own bare bones program. Forget about your framework, just use allegro. Either start from a wiki example, an allegro example, or from scratch. I know. Kris Asick said: When I have a free moment, I'll try to whip together a bare-bones program, but it may take awhile; I barely have time to work on code as it is. Again though, if there's some existing A5 programs I could test which run keyboard and joystick support at the same time, I could try those out too and see what happens. --- Kris Asick (Gemini) |
Thomas Fjellstrom
Member #476
June 2000
|
Quote: I know. Sorry. There was too much there to read I skimmed a bunch. Kris Asick said: Again though, if there's some existing A5 programs I could test which run keyboard and joystick support at the same time, I could try those out too and see what happens. ex_joystick_events already inits both. It only checks for ESC to quit, but it does stuff. -- |
Kris Asick
Member #1,424
July 2001
|
No worries, Thomas. When I get a chance I'll take a look at that example and see if I can use it as a base to add some keyboard input feedback, then report on what happens! A part of me is wondering though if perhaps any of this has to do with how Windows 8's legacy DirectInput support works... I do indeed plan to test my own code out on Dad's systems to see what happens too. For the interim, I've dummied out the joystick code in my input handler and will move on to XInput support for the time being, which from what I've seen from reading the XInput documentation, shouldn't be too difficult. At least Microsoft got SOMETHING right when making XInput: It's less complicated than DirectInput! TBH: While I'd like to include support for both, if I ultimately have to stick with just XInput I'm OK with this. Heck, given the nature of my project, having keyboard support only wouldn't technically be a faux pas, but I'd like to have at least SOME form of controller/joystick support present. I mean, I could go fetch my old DirectInput handler I made many years ago when I was unsatisfied with A4's input handling and retool it to work within A5, but I don't feel like that's a good use of my time, and I'm also somewhat worried the problem may be with Windows 8 and DirectInput and not with Allegro, and then there's always still a chance it's something I'm doing which just doesn't make any sense. Won't really know any of that until after testing my code on an older Windows system though. That will be Thursday night! EDIT: Just a quick update: I wasn't able to get around to testing any of this because I've been in pain since Thursday morning due to pulling a neck muscle just from stretching in a routine manner, so I've only been doing the minimum amount of work necessary to get by. I'll get around to testing this all out once I'm recovered. --- Kris Asick (Gemini) |
|