Skip to content
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

[SDL2][MacOS] Memory leak when opening a PS4 controller #9782

Open
tadashibashi opened this issue May 13, 2024 · 0 comments
Open

[SDL2][MacOS] Memory leak when opening a PS4 controller #9782

tadashibashi opened this issue May 13, 2024 · 0 comments
Assignees
Milestone

Comments

@tadashibashi
Copy link

Hello, there seems to be a memory leak whenever a PS4 controller is connected. The number of leaks increases when I disconnect and reconnect the controller. And using a generic usb controller, there are zero leaks.

Current version of SDL2: 2.30.3
MacOS version: Sonoma 14.4.1, arm64

Here's a minimal example that reproduces the leak. Maybe the problem is in my code.

#include <cstdio>
#include <cstring>
#include <SDL.h>

struct Controller {
    Controller() : id(-1), controller(nullptr) { }
    int id;
    SDL_GameController *controller;
};

int main(int argc, char *argv[])
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) != 0)
    {
        printf("Failed to initialize SDL2: %s\n", SDL_GetError());
        return -1;
    }

    auto window = SDL_CreateWindow("PS4 Controller Leak Test",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        400, 400, 0);
    if (!window)
    {
        printf("Failed to create window: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    printf("App initialized\n");

    Controller controllers[16] {};

    bool isRunning = true;
    while (isRunning)
    {
        SDL_Event e;
        while (SDL_PollEvent(&e))
        {
            switch(e.type)
            {
                case SDL_CONTROLLERDEVICEADDED:
                {
                    const auto index = e.cdevice.which;
                    const auto controller = SDL_GameControllerOpen(index);
                    if (!controller)
                    {
                        printf("Failed to open controller at index %d: %s\n",
                            index, SDL_GetError());
                        break;
                    }

                    const auto id = SDL_JoystickGetDeviceInstanceID(index);
                    if (id == -1)
                    {
                        printf("Failed to get Joystick instance id for controller at index %d: %s\n",
                            index, SDL_GetError());
                        break;
                    }

                    controllers[index].id = id;
                    controllers[index].controller = controller;
                    printf("Opened controller with id: %d\n", id);
                } break;

                case SDL_CONTROLLERDEVICEREMOVED:
                {
                    const auto id = e.cdevice.which;
                    for (auto &controller : controllers)
                    {
                        if (controller.id == id)
                        {
                            if (controller.controller)
                            {
                                SDL_GameControllerClose(controller.controller);
                                controller.controller = nullptr;
                                controller.id = -1;
                                printf("Closed controller with id: %d\n", id);
                            }
                            break;
                        }
                    }
                } break;

                case SDL_CONTROLLERBUTTONDOWN:
                {
                    const auto id = e.cbutton.which;
                    for (auto &controller : controllers)
                    {
                        if (controller.id == id)
                        {
                            printf("Pressed button %d on controller %d\n",
                                e.cbutton.button, id);
                            break;
                        }
                    }
                } break;

                case SDL_QUIT:
                {
                    isRunning = false;
                } break;
            }
        }
    }
    
    for (auto &controller : controllers)
    {
        if (controller.controller)
            SDL_GameControllerClose(controller.controller);
    }

    SDL_DestroyWindow(window);
    SDL_Quit();
    printf("App shutdown complete\n");
    return 0;
}

Running the program with MacOS leaks, it shows 5 leaks with a simple program run and quit when the PS4 controller is connected. (More occur when disconnecting and reconnect that controller). There are zero when it is disconnected and never connected when the program is running. The most clear leak points to a call to calloc in hidapi/mac/hid.c:867, function PLATFORM_hid_open_path

@tadashibashi tadashibashi changed the title [SDL][MacOS] Memory leak when opening a PS4 controller [SDL2][MacOS] Memory leak when opening a PS4 controller May 13, 2024
@slouken slouken self-assigned this May 22, 2024
@slouken slouken added this to the 3.2.0 milestone May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants