libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
10.19k stars 1.86k forks source link

SDL_PollEvent gives a sentinel event and returns true #11319

Open oh-facts opened 1 month ago

oh-facts commented 1 month ago

My game was working fine before. Then I updated my sdl and I noticed that my game was stuck in an infinite loop. Upon further investigation I found that control was stuck inside my event loop and it wouldn't break out because of a sentinel event.

SDL_Event sdl_event;
while (SDL_PollEvent(&sdl_event)) 
{
  if(sdl_event.type == SDL_EVENT_POLL_SENTINEL)
  {
   // I stepped through with a debugger to make sure that this was the reason
    break;
  }
  switch(sdl_event.type)
  {
   // handle other events
  }
}       

I haven't needed to break out explicitly before using the poll sentinel event. Also, I checked and the sentinel event is internal and ideally I shouldn't need to interact with it at all.

I made no changes to my code either, I just updated SDL.

The SDL3 commit is 638b50b69be6dd158e89d462dc786c067fc9e7ba. Also, SDL3 is built as a static library and the CRT is linked statically and this is debug mode. I compiled using the msvc compiler. This is C++.

PS: I explored a little more and I am quite confused now.

image image

Control is in the return false bit.

So, the event is a sentinel event, and false should be returned, right?

Here, is the part I don't get it.

image image

Why is res = 1 ? It clearly returned false right?

Let me know if I should provide more information.

Thank you.

oh-facts commented 1 month ago

I did some more work. So, this works fine with SDL2.

I don't think static linking is the issue here, since I used the same config for the sdl2 version (msvc, debug mode, static crt, static lib, C++).

I think it has to do something with that commit.

slouken commented 1 month ago

Can you reproduce it with an SDL test program? Most of them have that kind of loop structure.

oh-facts commented 1 month ago

sdl3_bug.zip

build.bat

This will build it and put the binary inside out/.

It uses msvc. In case you don't have the VS environment set up. You can do

call C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat

Keep me updated thank you

oh-facts commented 1 month ago

Also to clarify, It never quits the event loop. It gets a sentinel event and the poll events function returns true everytime. This will also make your app unresponsive, so be careful.

slouken commented 1 month ago

I see this output:

frame start
frame end
frame start
frame end
frame start
frame end
...

I'm linking with SDL dynamically though, maybe there's some issue with the way you've built your static library?

slouken commented 1 month ago

You may need to look at the disassembly and see why return false is turning into a return true.

oh-facts commented 1 month ago

I would appreciate it if you could statically link with SDL and also with the crt with msvc. I think this is a relevant detail. The zip I shared has that set up. I gave a reproducible build like you asked. If you think its a virus, perhaps you could build it yourself. I shared the commit # above where this problem occurs above.

Here is how I built it

cmake -S C:/dev/SDL -DSDL_STATIC=ON .

Then I opened the soln file and set the crt to link statically. Then I built sdl3-static. I then dropped it inside the root directory and you can see the build script to see what I did after. This is 1 to 1 recreation of my steps.

I am stepping through code and the poll events function takes me here

image

The return function does not return out of the function. It jumps here image

Here is the assembly instr. image image

I don't think I am doing something wrong since I built it again to verify.

This might not be directly related to sdl but something to do with the build system. I still think its worth exploring. Also, this problem is not there in sdl2. I followed these exact steps for it.

Thank you.

slouken commented 1 month ago

I tried using the binaries you provided and was able to reproduce the error, but I couldn't debug. I tried building static SDL using the steps you provided and got link errors:

LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4217: symbol '__stdio_common_vsprintf' defined in 'libucrt.lib(output.obj)' is imported by 'SDL3-static.lib(SDL_string.obj)' in function 'vsnprintf'
...
LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library
LINK : warning LNK4217: symbol '__stdio_common_vsprintf' defined in 'libucrt.lib(output.obj)' is imported by 'SDL3-static.lib(SDL_string.obj)' in function 'vsnprintf'

We strongly recommend dynamically linking with SDL. Please let me know if you run into this issue in that use case.

oh-facts commented 1 month ago

Doesn't work with the dll either. Everything is dynamically linked. Even the CRT. I have a reproducible build attached. I enabled debug symbols in the build script. Let me know if it works. sdl3 bug dll.zip

Thank you

madebr commented 1 month ago

What is the exact command you used for configuring SDL3 and building SDL3? What compiler version are you using?

I cannot reproduce it with MSVC 19.29.30154, nor with 19.41.34123, using the c source from https://github.com/libsdl-org/SDL/issues/11319#issuecomment-2436546054