libsdl-org / SDL_image

Image decoding for many popular formats for Simple Directmedia Layer.
zlib License
513 stars 174 forks source link

SEGMENTATION FAULT with IMG_Load_RW in SDL2 #424

Open oregu1 opened 5 months ago

oregu1 commented 5 months ago

Get into segmentation fault while running the project in mix with SDL2 & Wasm Workers. Segfault appears at SDL2 method IMG_Load_RW execution but can't understand why.

Version of emscripten/emsdk:

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.47 (431685f05c67f0424c11473cc16798b9587bb536)
clang version 18.0.0 (https://github.com/llvm/llvm-project 21030b9ab4487d845e29792063f5666d8c4b8e09)
Target: wasm32-unknown-emscripten
Thread model: posix

Uncaught RuntimeError: Aborted(segmentation fault)

Uncaught RuntimeError: Aborted(segmentation fault)
    at abort (mob1x.js:862:40)
    at segfault (mob1x.js:589:2)
    at imports.<computed> (mob1x.js:8326:24)
    at mob1x.wasm.SAFE_HEAP_STORE_i32_4_4 (mob1x.wasm:0xff1e37)
    at SDL_RWtell (SDL_rwops.c:798)
    at IMG_LoadPNG_RW (IMG_png.c:258)
    at IMG_LoadTyped_RW (IMG.c:289)
    at IMG_Load_RW (IMG.c:212)
    at mob1x.wasm._KBTexture2D::InitWithImage(char const*, DIRECTORY_TYPES, bool) (https://------/mob1x.wasm)
    at mob1x.wasm._KBTextureStorage::LoadTextureFromFile(char const*, DIRECTORY_TYPES, bool) (https://------/mob1x.wasm)
    at mob1x.wasm._KBGUIFont::InitFonts() (https://------/mob1x.wasm)
    at mob1x.wasm._KBGUI::Init() (https://------/mob1x.wasm)

user callback triggered after runtime exited or application aborted. Ignoring.

user callback triggered after runtime exited or application aborted.  Ignoring. 2 [mob1x.js:4540:6](https://------/mob1x.js)
    callUserCallback https://------/mob1x.js:4540
    doCallback https://------/mob1x.js:6848
    reportReadyStateChange https://------/mob1x.js:6869
    onreadystatechange https://------/mob1x.js:6703
    (Async: EventHandlerNonNull)
    fetchXHR https://------/mob1x.js:6694
    performUncachedXhr https://------/mob1x.js:6874
    onsuccess https://------/mob1x.js:6786
    (Async: EventHandlerNonNull)
    fetchLoadCachedData https://------/mob1x.js:6768
    _emscripten_start_fetch https://------/mob1x.js:6905
    x https://------/mob1x.js:8326
    emscripten_fetch https://------/mob1x.wasm:1527442
    mob1x.wasm._KBHTTPQuery::Run() https://------/mob1x.wasm:1548884
    mob1x.wasm._KBHTTPManager::RunQuery(_KBHTTPQuery*) https://------/mob1x.wasm:1838212
    mob1x.wasm._KBHTTPManager::AddQuery(_KBHTTPQuery*) https://------/mob1x.wasm:1837294
    mob1x.wasm._KBHTTPManager::Get(char const*, _KBHTTPQueryCallback*, bool, int) https://------/mob1x.wasm:614490
    mob1x.wasm._KBResourceManager::CheckoutResourceVersion(int) https://------/mob1x.wasm:1983027
    mob1x.wasm._KBResourceManager::Init() https://------/mob1x.wasm:883127
    mob1x.wasm._KBCore::Init() https://------/mob1x.wasm:879105
    mob1x.wasm.initCore() https://------/mob1x.wasm:14950189
    mob1x.wasm.allocateSystem() https://------/mob1x.wasm:96246
    dynCall_v https://------/mob1x.wasm:16697430
    x https://------/mob1x.js:8348
    createExportWrapper https://------/mob1x.js:884
    browserIterationFunc https://------/mob1x.js:6291
    callUserCallback https://------/mob1x.js:4544
    runIter https://------/mob1x.js:4618
    Browser_mainLoop_runner https://------/mob1x.js:4519
    (Async: FrameRequestCallback)
    requestAnimationFrame https://------/mob1x.js:4858
    Browser_mainLoop_scheduler_rAF https://------/mob1x.js:1557
    Browser_mainLoop_runner https://------/mob1x.js:4523
    (Async: FrameRequestCallback)
    requestAnimationFrame https://------/mob1x.js:4858
    Browser_mainLoop_scheduler_rAF https://------/mob1x.js:1557
    Browser_mainLoop_runner https://------/mob1x.js:4523
    (Async: FrameRequestCallback)
    requestAnimationFrame https://------/mob1x.js:4858
    Browser_mainLoop_scheduler_rAF https://------/mob1x.js:1557
    setMainLoop https://------/mob1x.js:4531
    _emscripten_set_main_loop https://------/mob1x.js:6292

CMakeLists.txt config

(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(USE_FLAGS "-sUSE_ZLIB=1 -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=['png,jpg'] -O0 -flto -g -sWASM_WORKERS=1" CACHE STRING "Compilation flags" FORCE)

    set(LINKING_FLAGS "--preload-file ${ASSETS_PATH}/assets@/assets -sFULL_ES2 -sWASM=1 -sFETCH=1 --use-preload-plugins -sEXIT_RUNTIME=1 -sALLOW_MEMORY_GROWTH=1 -sEXPORTED_FUNCTIONS=['_main','_photoTaken','_malloc','_setNotificationToken','_interceptPushNotification'] -sEXPORTED_RUNTIME_METHODS=[cwrap] -sFORCE_FILESYSTEM=1 -lidbfs.js -O0 -flto -g -sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY -sASYNCIFY_STACK_SIZE=65536 -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=['png,jpg'] -sSAFE_HEAP=1" CACHE STRING "Linking flags" FORCE)

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${USE_FLAGS}")

    add_definitions(-DTARGET_WEB -DDEBUG -DMA_ENABLE_AUDIO_WORKLETS)

Source code

SDL_Surface *imgRef = 0;

    if(filePath)
    {
        char * buffer = 0;
        long bufferLength = 0;

        FM->LoadDataAsset(filePath, &buffer, &bufferLength);

        if(buffer)
        {
            SDL_RWops* rw = SDL_RWFromConstMem(buffer, bufferLength);
            if(rw)
                imgRef = IMG_Load_RW(rw, 1); //1 to release/free RWops
            free(buffer);
        }
    }

    if (imgRef)
    {
        if (imgRef->format->format == SDL_PIXELFORMAT_ABGR8888)
            pixelFormat = kTexture2DPixelFormat_RGBA8888;
        else if (imgRef->format->format == SDL_PIXELFORMAT_RGBA4444)
            pixelFormat = kTexture2DPixelFormat_RGBA4444;
        else if (imgRef->format->format == SDL_PIXELFORMAT_RGB24)
            pixelFormat = kTexture2DPixelFormat_RGB24;
        else if (imgRef->format->format == SDL_PIXELFORMAT_INDEX8)
            pixelFormat = kTexture2DPixelFormat_A8;

        InitWithData(imgRef->pixels, pixelFormat, imgRef->w, imgRef->h, alias);

        SDL_FreeSurface(imgRef); 
        return true;
    }

    return false;
LoadDataAsset(const char * assetName, char ** buffer, long* length)
{
    FILE * file = fopen(assetName, "rb");
    if(file) {
        fseek(file, 0, SEEK_END);
        *length = ftell(file);
        fseek(file, 0, SEEK_SET);

        *buffer = (char *) malloc(*length + 1);
        fread(*buffer, *length, 1, file);

        fclose(file);
    }
}
slouken commented 5 months ago

Do you have the source code for SDL_image and SDL that is being used? Those line numbers don't correspond to the latest release.

oregu1 commented 5 months ago

Our project is made with emscripten version 3.1.47 where SDL2 as port is used and I can't say what version is ported there. Actually I don't know right now how to do it. The only thing that I found is that in emsdk folder generated by emscripten lies sdl2_image.6.0.zip & sdl2.24.2.zip archives. Hope it will help somehow.

oregu1 commented 5 months ago

Do you have the source code for SDL_image and SDL that is being used? Those line numbers don't correspond to the latest release.

@slouken I've found what SDL version is used in my project. It's 2.24.2 for SDL and 6.0 for SDL2_image

oregu1 commented 5 months ago

@slouken Sam any ideas???