It's been a long time since I posted here but I'm just trying to get back into Allegro and I just hit this. Why does the following code hang?:
#include <allegro5/allegro.h>
ALLEGRO_DISPLAY *display = NULL;
int main() {
assert(al_init());
assert(al_install_keyboard());
assert(al_install_mouse());
al_set_new_display_flags(ALLEGRO_WINDOWED);
display = al_create_display(800, 600);
assert(display);
// al_flip_display();
}
I know this code is pretty much useless but I find it still weird that it hangs. I'm using Debian Stretch and Allegro 5.2.2 from the official repository. Uncommenting the last line makes the code work as expected so it's not really that much of a big deal but I was puzzled by hitting this, mainly because I thought I had an error in my initialization code (not shown here).
- I would make sure you've got a proper compiled version of Allegro. No "multiple versions on my system" that'll blow up if the installed vs compiled are different.
- Does removing windowed mode affect it?
Run gdb ./my_program, then as it halts, in the gdb terminal hit control-C. That'll stop execution. You can then type bt for backtrace and it will show you the function stack where everything is frozen.
When you say, "halt" you mean it freezes right? Not "it crashes to desktop/terminates". Though, even if it does that, gdb will tell you a hint of why.
- One more clarification: You gave us sample code. Does that sample code (exactly as written) do what you describe?
[edit] What's your hardware look like? Do you have multiple graphics adapters?
ALLEGRO_WINDOWEDPrefer a windowed mode.
Under multi-head X (not XRandR/TwinView), the use of more than one adapter is impossible due to bugs in X and glX. al_create_display will fail if more than one adapter is attempted to be used.
[edit]
Yep. I compiled it with my distribution (took awhile since I always use D now!). It runs fine. It doesn't freeze or "halt." It does exit to desktop successfully.
Definitely recheck your Allegro installation. Make sure there is only one version, or, that you are linking and compiling with exactly one version.
So at this point it seems like it's reduced to either:
- Allegro lib linking error (as mentioned above).
- Some hardware or driver specific bug.
- An Allegro bug that fails only with your specific OS, hardware, etc.
-----sig:“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
[EDIT:] You edited you post as I was writing mine. I guess I'm gonna build Allegro myself and make some tests. I've built it before but this time I was being lazy and decided to use the version from the Debian repository. I will report back the results. Thanks.
[Original post follows]
- I would make sure you've got a proper compiled version of Allegro. No "multiple versions on my system" that'll blow up if the installed vs compiled are different.
I have only the version from the official Debian repository installed.
- Does removing windowed mode affect it?
Same result. Actually, the following code has the same issue. I guess it can't be smaller than that:
#include <allegro5/allegro.h>
ALLEGRO_DISPLAY *display = NULL;
int main() {
assert(al_init());
display = al_create_display(800, 600);
assert(display);
// al_flip_display();
}
When you say, "halt" you mean it freezes right? Not "it crashes to desktop/terminates".
That's right, the Allegro window freezes. I'd expect the Allegro window to appear as I call al_create_display() and then to close immediately; instead, the Allegro window remains onscreen and I have to force the program termination.
- One more clarification: You gave us sample code. Does that sample code (exactly as written) do what you describe?
Yes, as does the code posted here.
What's your hardware look like? Do you have multiple graphics adapters?
Just a single AMD graphics card:
OpenGL renderer string: Gallium 0.4 on AMD CEDAR (DRM 2.49.0 / 4.9.0-4-amd64, LLVM 3.9.1)
I'm gonna try running it with gdb now.
[EDIT 2:] Built Allegro 5.2.3 and got the same result. Weird. This is gbd's backtrace:
(gdb) run
Starting program: /home/ken/code/allegro/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff3048700 (LWP 11910)]
Allegro version: 5.2.2
[New Thread 0x7fffed11e700 (LWP 11911)]
[Thread 0x7fffed11e700 (LWP 11911) exited]
[Thread 0x7ffff3048700 (LWP 11910) exited]
^C <-- Forced program termination here
Thread 1 "a.out" received signal SIGINT, Interrupt.
pthread_cond_wait@@GLIBC_2.3.2 ()
at ../sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
185 ../sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: No such file or directory.
(gdb) bt
#0 pthread_cond_wait@@GLIBC_2.3.2 ()
at ../sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
#1 0x00007ffff1e9893b in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#2 0x00007ffff21cde2f in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#3 0x00007ffff21edef6 in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#4 0x00007ffff21ecd7e in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#5 0x00007ffff1caaaf4 in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#6 0x00007ffff1b5c448 in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#7 0x00007ffff1ceb5ab in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#8 0x00007ffff1dfe04f in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#9 0x00007ffff1dfdafa in ?? () from /usr/lib/x86_64-linux-gnu/dri/r600_dri.so
#10 0x00007ffff62374f5 in glXMakeCurrentReadSGI ()
from /usr/lib/x86_64-linux-gnu/libGL.so.1
#11 0x00007ffff7b2eb44 in al_set_target_bitmap ()
from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2
#12 0x00007ffff7b1a54f in al_destroy_display ()
from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2
#13 0x00007ffff7b76df2 in ?? ()
from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2
#14 0x00007ffff7b2bf35 in ?? ()
from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2
#15 0x00007ffff7b1feed in _al_run_exit_funcs ()
from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2
---Type <return> to continue, or q <return> to quit---
#16 0x00007ffff7b2c015 in al_uninstall_system ()
from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2
#17 0x00007ffff754b910 in __run_exit_handlers (status=0,
listp=0x7ffff78af5d8 <__exit_funcs>,
run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true)
at exit.c:83
#18 0x00007ffff754b96a in __GI_exit (status=<optimized out>) at exit.c:105
#19 0x00007ffff75362b8 in __libc_start_main (main=0x555555554a30 <main>,
argc=1, argv=0x7fffffffe258, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7fffffffe248)
at ../csu/libc-start.c:325
#20 0x000055555555492a in _start ()
(gdb) q
A debugging session is active.
Inferior 1 [process 11903] will be killed.
Quit anyway? (y or n) y
It's probably a problem with my Linux distro?. Anyway, it's not a big deal since a typical Allegro 5 program execution wouldn't hit this issue, I guess, as calling al_flip_display() seems to solve the problem. Posting it here just in case it's of some use.
Thanks.
Have you tried updating your graphics drivers? Any other games cause this problem? try "glxgears".
This guy has the same problem with Payday 2 in Linux.
Here's more listings regarding that driver and pthread_wait
It could be the distro files, or, driver related files.
This one mentions after updating from Mesa 11 to Mesa 12 (plus other updates) the hang is gone:
I just tested with Mesa 12.0.1, libdrm 2.45.0, kernel 4.7, libdrm 2.4.70 and the hang seems to be gone. I am marking this bug as fixed.
Thank you for your work!
(Complete wild guess) I almost wonder if there's some sort of pthread related wait condition tied to VSYNC and for some strange reason VSYNC never fires off. I wonder if forcing VSYNC on, or off, changes it. You can test that with:
export vblank_mode=0 //one of these then your program
export vblank_mode=1
export vblank_mode=2
export vblank_mode=3
//or,
vblank_mode=0 ./my_program
//etc
(I can't remember which is "force on" and which is "force off", try all four. )
[edit]
FINALLY found a source that mentions what they do instead of saying 'just use this' with no documentation:
vblank_mode=0 mean disabled by default
vblank_mode=1 mean application choice, but enabled by default
vblank_mode=2 mean application choice, but disabled by default
vblank_mode=3 mean enabled by default
So try 0 and 3.
Thanks for the thorough answer. It does indeed seem like a driver issue as described in the links you posted, and not Allegro related as I originally thought.
There are two Radeon drivers on Debian (free and non-free) so I might as well try with the non-free driver.
Setting vblank_mode didn't have any effect, the result is the same. Also, Debian Stretch comes with Mesa 13.0.6 and libdrm 2.4.74, so it seems there's still a bug in the free Radeon driver.
Not a big deal, for Allegro at least, since a proper game loop should work fine. May this post help other users who might hit this.
Thanks again.
Instead of 'bt', try 'thread apply all bt'. You will get to see if there are any other threads hanging around. You can also do 'info threads' to see which threads.
Neat! I learned something about gdb today.
Another thing you can do is use strace which lists all system/kernel calls coming from your application. (It can also do a summary mode which lists time spent longest in what calls.)
strace ./my_program
[...]
ioctl(6, DRM_IOCTL_I915_GEM_MADVISE, 0x7ffde80b13d0) = 0
ioctl(6, DRM_IOCTL_I915_GEM_MADVISE, 0x7ffde80b13b0) = 0
ioctl(6, DRM_IOCTL_I915_GEM_BUSY, 0x7ffde80b1370) = 0
ioctl(6, DRM_IOCTL_I915_GEM_MADVISE, 0x7ffde80b1360) = 0
[...]
My graphics driver is i915. If it halts, those messages would likely stop spamming the console on a specific "wait for event"-like message.
strace -c ./my_program
Outputs the summary table / c="counts" of calls and how much time they took individually and total. Usually that's not a problem for us userland programmers but you can tell when you're spamming way too many calls, or, theoretically, if "one call" were to magically halt and freeze, strace would still be calculating the time it took. So after a few seconds of being halted, the faulty function would then be at the top of the total execution time. So when you then force an exit, you would (theoretically) see a list of the calls where it froze.
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
87.76 0.040996 1 75539 6 ioctl
8.56 0.004000 95 42 munmap
3.29 0.001538 0 6420 poll
0.20 0.000094 0 3756 writev
Of course, it's likely a driver problem. But gdb and strace can help you find whether an issue is your code, the library code (like Allegro), a higher level bug like OpenGL, or even driver problems.
I also just realized you can do "bt full" which will show all local variables for all frames. That's pretty handy.
I'm actually planning on trying gdbgui, which is a front-end for GDB and is inspired by Google's Chrome debugger: