I’ve been probing this crash thing a little further, and wanted to add a
few new details.
First of all, I can reproduce the crash when someone else builds on a
different machine; therefore I conclude the problem is not related to
any particularities in my build system.
Second, the joystick that causes the crash is the Saitek P480 Rumble Pad
(or at least Windows recognizes it as such). I have two of these
sticks, and both cause the problem. Therefore I conclude that it is not
a particular joystick that is the problem, though the problem could be
related to the model.
Third, I tried running the testjoystick code that comes with SDL, and it
exhibits the same problem. This removes any doubt that it is related to
Bitfighter.
So… that’s the state of things.
ChrisOn 10/8/2013 10:37 PM, Watusimoto wrote:
One more thing… if I remove the JoystickOpen and JoystickClose
lines, the crashes go away.On 10/8/2013 10:31 PM, Watusimoto wrote:
Hi again,
As I wrote in an earlier message, I was able to pare the game code
down a bit to focus on the source of the crash. I pared pretty much
down to the bone, and am now left with this:int main(int argc, char **argv)
{
SDL_Init(0);
SDL_JoystickEventState(SDL_ENABLE);
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
SDL_Joystick *x = SDL_JoystickOpen(0);
SDL_JoystickClose(x);SDL_QuitSubSystem(SDL_INIT_JOYSTICK); exit(0);
}
The code above works fine (i.e. no crash, calm exit) when there is no
stick plugged in.
I have two sticks, one marked “hama” (the blue one), and one marked
"saitek" (the silver one). Both sticks are known to work.
When the blue stick is in, it works fine.
When the silver stick is in, this crashes, ether on the
QuitSubSystem() or on the exit.
If both are in, it also crashes, regardless of which I plug in first.
If both are in and it crashes, and I unplug the silver stick, it
stops crashing.The stack trace is useless. But I copied it here anyway:
http://pastebin.com/KDRHGx4WI’m not sure what to do next. Any thoughts?
Chris
On 10/7/2013 10:47 AM, T. Joseph Carter wrote:
I’ve spent a lot of time with the joystick API in the past couple of
weeks. I’m not immediately sure of the problem you’re having and
whether it’s your code or SDL’s that’s causing it from what you’ve
posted so far. Maybe I can help anyway.As you probably know, SDL_NumJoysticks returns the number of
joysticks found on the system. If you run a program and it iterates
through the joysticks, you may find, for example:0: XBox 360 controller
1: Logitech F-310 controller
2: USB NES controllerNow, let’s say you disconnect the Logitech. The NES controller
moves down to index 1. If you reconnect the Logitech, it’ll be
index 2. If you quit the program and restart it, the order may
change depending on what the OS tells SDL. In fact, once the
joystick is open the device index is irrelevant. You cannot even
query it via function, and you don’t need to.Internally SDL uses instance IDs. These are never renumbered, nor
are they recycled. If you unplug a joystick, its old instance ID is
dead. If you reconnect it, you get a new instance. Theoretically
you could smash the instance counter, but I don’t happen to care
because I’m going to be long dead by the time you manage to do it.I consider iterating over SDL_NumJoysticks() to basically be a
legacy API, mostly because it’s useful for developers to be able to
spit out the list of recognized joysticks on the system right now,
perhaps along with GameController mappings (but that’s a separate
API?) I’d suggest deprecating such a construct for any other
purpose, at least within SDL’s own example code. Which probably
means Sam’s going to tell me to get off my something or other and do
it.The reason why you needn’t iterate over SDL_NumJoysticks is that
when SDL first inits the joystick subsystem, it emits
SDL_JOYDEVICEADDED events for every joystick currently on the
system. That means you don’t have to open and use any joysticks
there at startup, then write an event handler to also use any that
get added. Write it once as an event handler and be done.Some notes:
You can open a joystick more than once. SDL refcounts
joysticks. If you SDL_JoystickOpen a device twice, the two
SDL_Joystick structures both access the same stick. If one is
closed, the other is maintained until it too is closed.You can never count on the order of joysticks presented to you,
and you should not. Moreover, GUIDs are often completely arbitrary
and are not ever going to be unique to the device. Connect two PS3
controllers and you’re going to have two devices with the same
GUID. For multiplayer, this means you either let the user choose
the number of players and have each user do something in sequence to
tell you which player is which, or you do it arcade style where the
game starts single player, and players 2, 3, 4 can join by pressing
start (or whatever?)In an event-driven SDL application using joysticks, you won’t
need the SDL_Joystick pointer for most things. You open it, query
its features, and then? listen for events from it. Events will refer
to instance IDs directly, and quitting the joystick subsystem will
destroy all SDL_Joysticks (with any pointers you had now being
invalid?)SDL_JOYDEVICEREMOVED does not appear to close an opened
joystick. It’s just letting you know that the given joystick for
the instance in question is gone and you can stop trying to access
it. If you kept track of multiple players’ SDL_JoystickIDs from my
suggestion in #2 above, you’ll know which player has dropped out of
the game.I can say that on SDL_JOYDEVICEREMOVED, memory is not freed. If
you have the SDL_Joystick pointer, it’s not going to work. If you
have it, you theoretically could SDL_JoystickClose it, but I’m not
even 100% sure that’s what you should do.Bonus thoughts for the GameController API:
Although the idea is that SDL will have an extensive built-in DB
of mappings for the GameController API, it doesn’t. Nonetheless,
this is a solvable problem, so if you don’t need arbitrary numbers
of buttons, hats, trackballs, etc., it’s worth a look.The reason GameControllers are a solvable problem is that an
opened GameController is also an opened Joystick. It continues to
send Joystick events. You can use this to allow players to remap
their controls in-game. The problem here is that there’s no sane
way to get SDL to tell you what the current mapping is. The only way
I know of at present is to ask for the complex config string SDL
parses internally and to parse it yourself. This is a problem I
intend to solve as soon as I’m done documenting the joystick API.Hopefully some of that will help you identify the problem?
Joseph
On Mon, Oct 07, 2013 at 12:46:01AM +0200, Watusimoto wrote:
Hello,
I’m having a very strange problem with joysticks in SDL2, using a
build of SDL based on code downloaded this evening. I’m working on
Windows, and built with the VC++ 10 EE project.When I have a joystick plugged into my game, I get weird and
semi-random crashes that have all the hallmarks of a memory
corruption issue, something like a double-delete or related fault.The overall program is fairly complex, but what we do is this,
essentially:
- Grab a joystick:
sdlJoystick = SDL_JoystickOpen(0); // only place sdlJoystick
is assigned
if(sdlJoystick == NULL) { /* error handling that is never
triggered */ }We can use this joystick for playing, and everything works fine.
Until, that is, we try to reacquire the joysticks (which we do to
see if a user has plugged a new stick in):// [A] Close if already open
if(sdlJoystick)
{
TNLAssert(SDL_JoystickGetAttached(sdlJoystick), “Problem! –
never triggered”);
SDL_JoystickClose(sdlJoystick);
sdlJoystick = NULL;
}// [B] Will need to shutdown and init, to allow SDL_NumJoysticks
to count new joysticks
if(SDL_WasInit(SDL_INIT_JOYSTICK))
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);// [C] Initialize the SDL subsystem
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK))
{
logprintf(“Unable to initialize the joystick subsystem”);
return false;
}The code usually crashes in [A] (in JoystickClose) or [B] (never in
[C]), but the crashes are somewhat random. For a while it was only
crashing every 5 passes or so, but now it crashes every time
through. Debugging into the SDL code shows it crashing in all sorts
of random places inside SDL_JoystickClose() or SDL_QuitSubSystem(),
even places it should never crash, like comparing two pointers.
Hence my conclusion that it must be memory related.I have verified that sdlJoystick is unmolested, and I can find no
obvious null pointers or similar problems in our code or the SDL
code. We use SDL for other things, such as screen rendering,
without apparent problem.I am currently a bit stuck. I’m looking for suggestions on how to
further debug this problem. Any ideas?Thanks much,
Chris
PS Our code is open, so I can share more if it would be helpful.
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org