Posted June 09, 2016
Hi, I just bought this game yesterday. Today I launched the game, and it froze while I was in the menu making changes. Retried a few times, and it always froze in the menu eventually. The randomness of it made me suspect a race. Later I found that moving the mouse wildly around for a while [to generate lots of input events] makes it easy to trigger this condition.
So I ran strace on the main thread and noted that when the game is not frozen, the event loop uses cycles between two futexes regularly. Right when the game freezes, a third futex never seen before and never used by any other thread enters the picture. The main thread waits on it. Nobody wakes it up. Likely deadlock?
gdb gives me a clue:
# gdb -tui -p `pgrep Render`
...
0xf76feba0 in __kernel_vsyscall ()
(gdb) up
#1 0xf76c3a2b in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib32/libpthread.so.0
(gdb) up
#2 0xf6dfc3bc in ?? ()
(gdb) disas $pc-20,+40
Dump of assembler code from 0xf6dfc3a8 to 0xf6dfc3d0:
0xf6dfc3a8: add $0xc,%esi
0xf6dfc3ab: mov $0x1,%edi
0xf6dfc3b0: mov %esi,0x4(%esp)
0xf6dfc3b4: mov %edx,(%esp)
0xf6dfc3b7: call 0xf6dfbad0
=> 0xf6dfc3bc: jmp 0xf6dfc353
0xf6dfc3be: xchg %ax,%ax
0xf6dfc3c0: test %edi,%edi
0xf6dfc3c2: je 0xf6dfc344
0xf6dfc3c4: mov 0x5150(%esi),%eax
0xf6dfc3ca: test %eax,%eax
0xf6dfc3cc: jne 0xf6dfc5d2
End of assembler dump.
This address range resides in a copy of libxcb shipped with the game:
$ cat /proc/`pgrep Render`/maps
...
f6df4000-f6e14000 r-xp 00000000 08:21 7488386 /home/duclare/GOG Games/Victor Vran/game/i386/usr/lib/i386-linux-gnu/libxcb.so.1.1.0
...
$ objdump -d '/home/duclare/GOG Games/Victor Vran/game/i386/usr/lib/i386-linux-gnu/libxcb.so.1.1.0'
...
83a1: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi
83a8: 83 c6 0c add $0xc,%esi
83ab: bf 01 00 00 00 mov $0x1,%edi
83b0: 89 74 24 04 mov %esi,0x4(%esp)
83b4: 89 14 24 mov %edx,(%esp)
83b7: e8 14 f7 ff ff call 7ad0 <pthread_cond_wait@plt>
83bc: eb 95 jmp 8353 <xcb_connect_to_fd+0x483>
...
Unfortunately the binary looks optimized and lacking in symbols with a ton of stuff going under xcb_connect_to_fd. I didn't want to try and follow the trail of jumps in assembly to figure out how we got here and why the third mutex, so I decided to look for the source. I stumbled upon xcb's home page, and per chance took a glance at the release notes for the last two releases. Hey, look:
Hi everyone,
there is a new minor version of libxcb available. This fixes some
threading-related bugs with xcb_wait_for_special_event() and adds
64-bit versions of functions that work with sequence numbers.
[..]
Fix a thread hang with xcb_wait_for_special_event()
[..]
Am I wasting time on a known and fixed issue? I noticed I already have the latest version of libxcb (1.11.1) installed at /usr/lib32/libxcb.so.1.1.0. So I moved out the version shipped with the game, and in its place copied my local version.
Now the menu runs great without freezing.
I've yet to try the game.
Please patch this issue ASAP before more people waste time on it :)
So I ran strace on the main thread and noted that when the game is not frozen, the event loop uses cycles between two futexes regularly. Right when the game freezes, a third futex never seen before and never used by any other thread enters the picture. The main thread waits on it. Nobody wakes it up. Likely deadlock?
gdb gives me a clue:
# gdb -tui -p `pgrep Render`
...
0xf76feba0 in __kernel_vsyscall ()
(gdb) up
#1 0xf76c3a2b in pthread_cond_wait@@GLIBC_2.3.2 () from /usr/lib32/libpthread.so.0
(gdb) up
#2 0xf6dfc3bc in ?? ()
(gdb) disas $pc-20,+40
Dump of assembler code from 0xf6dfc3a8 to 0xf6dfc3d0:
0xf6dfc3a8: add $0xc,%esi
0xf6dfc3ab: mov $0x1,%edi
0xf6dfc3b0: mov %esi,0x4(%esp)
0xf6dfc3b4: mov %edx,(%esp)
0xf6dfc3b7: call 0xf6dfbad0
=> 0xf6dfc3bc: jmp 0xf6dfc353
0xf6dfc3be: xchg %ax,%ax
0xf6dfc3c0: test %edi,%edi
0xf6dfc3c2: je 0xf6dfc344
0xf6dfc3c4: mov 0x5150(%esi),%eax
0xf6dfc3ca: test %eax,%eax
0xf6dfc3cc: jne 0xf6dfc5d2
End of assembler dump.
$ cat /proc/`pgrep Render`/maps
...
f6df4000-f6e14000 r-xp 00000000 08:21 7488386 /home/duclare/GOG Games/Victor Vran/game/i386/usr/lib/i386-linux-gnu/libxcb.so.1.1.0
...
$ objdump -d '/home/duclare/GOG Games/Victor Vran/game/i386/usr/lib/i386-linux-gnu/libxcb.so.1.1.0'
...
83a1: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi
83a8: 83 c6 0c add $0xc,%esi
83ab: bf 01 00 00 00 mov $0x1,%edi
83b0: 89 74 24 04 mov %esi,0x4(%esp)
83b4: 89 14 24 mov %edx,(%esp)
83b7: e8 14 f7 ff ff call 7ad0 <pthread_cond_wait@plt>
83bc: eb 95 jmp 8353 <xcb_connect_to_fd+0x483>
...
Hi everyone,
there is a new minor version of libxcb available. This fixes some
threading-related bugs with xcb_wait_for_special_event() and adds
64-bit versions of functions that work with sequence numbers.
[..]
Fix a thread hang with xcb_wait_for_special_event()
[..]
Now the menu runs great without freezing.
I've yet to try the game.
Please patch this issue ASAP before more people waste time on it :)