-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect use of SDL_GetError() to check whether calls failed #257
Comments
SDL_GetError works like Standard C errno: if a call fails it will (generally) set the error indicator, but if a call succeeds there is no guarantee about whether the error indicator has been set, cleared, or left at its previous value. The SDL documentation says this: The message is only applicable when an SDL function has signaled an error. You must check the return values of SDL function calls to determine when to appropriately call SDL_GetError(). You should not use the results of SDL_GetError() to decide if an error has occurred! Sometimes SDL will set an error string even when reporting success. In particular, with a SDL 2.27.x git snapshot, a successful SDL_Init can leave the error indicator set to a message about inability to open an input device node, and this does not mean it has failed. In this commit I have not attempted to check or fix other uses of SDL_GetError, only the ones that follow SDL_Init. This is enough to make the test suite pass on Debian 12 alpha with `SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy SDL_RENDER_DRIVER=software` for now, but the other SDL_GetError() calls in the test suite should ideally also be checked. Partial solution for: py-sdl#257 Signed-off-by: Simon McVittie <smcv@collabora.com>
#258 partially solves this. A complete solution for this would be to apply similar changes to all the other |
SDL_GetError works like Standard C errno: if a call fails it will (generally) set the error indicator, but if a call succeeds there is no guarantee about whether the error indicator has been set, cleared, or left at its previous value. The SDL documentation says this: The message is only applicable when an SDL function has signaled an error. You must check the return values of SDL function calls to determine when to appropriately call SDL_GetError(). You should not use the results of SDL_GetError() to decide if an error has occurred! Sometimes SDL will set an error string even when reporting success. In particular, with a SDL 2.27.x git snapshot, a successful SDL_Init can leave the error indicator set to a message about inability to open an input device node, and this does not mean it has failed. In this commit I have not attempted to check or fix other uses of SDL_GetError, only the ones that follow SDL_Init. This is enough to make the test suite pass on Debian 12 alpha with `SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy SDL_RENDER_DRIVER=software` for now, but the other SDL_GetError() calls in the test suite should ideally also be checked. Partial solution for: #257 Signed-off-by: Simon McVittie <smcv@collabora.com>
Adding this to the to-do milestone for the next release! I should also make sure |
Thanks for working on improving this, but this issue is unresolved, so please reopen. There are still lots of places in the tests that assert that some operation left the error indicator empty, for example:
|
On my Linux system, enumeration succeeds, but the error indicator gets set as a side-effect (which appears to be because the loader checks whether the symbol exists in SDL or a direct dependency before it dlopens libudev). The API of SDL_hid_enumerate does not make it possible to distinguish between successfully returning an empty list of devices (returns NULL with the error indicator in an undefined state) and a failure (returns NULL with the error indicator set), and systems that run automated tests usually don't have any HID game controllers connected, so we can't make any meaningful use of the error indicator here. Helps: py-sdl#257 Signed-off-by: Simon McVittie <smcv@debian.org>
Helps: py-sdl#257 Signed-off-by: Simon McVittie <smcv@debian.org>
…ilure SDL_GetError() is like errno: it's documented not to be suitable for detecting failure, only for getting more details if failure was already detected (its result is unspecified on success, because a successful API call might have been implemented by doing something that failed, detecting that, and falling back to doing something different). However, some functions in SDL2 return void, so we have no other way to tell whether they have failed (they do return a result in SDL3). To make it less likely that upgrading SDL2 will make these tests regress, clear the error indicator immediately before calling the function under test. It is still not guaranteed to be empty on success, but at least this way we make sure it doesn't already contain an error message from a previous function call. Helps: py-sdl#257 Signed-off-by: Simon McVittie <smcv@debian.org>
Oops. I thought I did a search through the codebase for incorrect Also, thanks a ton for your continued efforts upstreaming fixes for bugs in the test suite (and elsewhere): I'm not a software developer by trade, so there's been a lot of learning-as-I-go in taking over maintenance of a project like PySDL2 (especially in terms of unit tests). I apologize that you've had to spend so much time fixing my failing tests as a result, but I sincerely appreciate your detailed bug reports and clean, well-documented patches. |
On my Linux system, enumeration succeeds, but the error indicator gets set as a side-effect (which appears to be because the loader checks whether the symbol exists in SDL or a direct dependency before it dlopens libudev). The API of SDL_hid_enumerate does not make it possible to distinguish between successfully returning an empty list of devices (returns NULL with the error indicator in an undefined state) and a failure (returns NULL with the error indicator set), and systems that run automated tests usually don't have any HID game controllers connected, so we can't make any meaningful use of the error indicator here. Helps: #257 Signed-off-by: Simon McVittie <smcv@debian.org>
I should probably mention why I keep opening issues about breakage with new SDL versions, to give you some context. In Debian, we have both SDL2 and pysdl2 available as packages. We regularly run pysdl2's test suite, and when there's a new version of SDL2 waiting to be integrated, one of the things our QA infrastructure does is to run the old pysdl2's test suite against the new SDL2. If it fails, there are two possible reasons for that:
I'm a maintainer of our SDL2 package, and when I upload new SDL2 versions, it's relatively common for them to get stuck and not be integrated immediately, because the pysdl2 test suite started failing; so to get the new SDL2 out to users, I have to dig into pysdl2 and find out whether we're in scenario 1 or 2. If we're in scenario 1, great, a regression was successfully caught, and I need to get SDL2 fixed; but if we're in scenario 2, then I need to either fix pysdl2 or get it kicked out of the development branch of Debian, otherwise SDL2 can't progress. Obviously I prefer to fix potentially-useful software rather than removing it, hence the merge requests. I'm not actually entirely clear on why we have pysdl2 in Debian, because we don't seem to have any games or apps that depend on it - but its test coverage is currently broader than SDL's, so it's a good way to check that SDL hasn't obviously broken something, and if it occasionally detects a genuine regression in SDL2 then that's enough to earn its place. |
@smcv Ah, that makes perfect sense. Interesting that PySDL2 got added as a package if it wasn't needed for anything... looks like someone just requested it back in 2013 and it's been around ever since! I'm glad to hear the test suite has proved useful for catching upstream SDL bugs: I've spent a lot of time and effort cleaning up/expanding the test suite at this point, so I'm glad it's paying off for something other than just making sure my bindings are correct! Hopefully with the latest set of fixes it'll be less likely to give you false positives. |
The SDL documentation says this:
However, the pysdl2 test suite has a lot of this pattern, which the quoted documentation calls out as incorrect:
What doesn't work?
One concrete example is that when I run the test suite on Debian 12 alpha, I get a lot of failures like this:
How To Reproduce
I'm using a SDL 2.27.x git snapshot from 2023-01-03, in case it matters.
Platform (if relevant):
The text was updated successfully, but these errors were encountered: