镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

nvExit() never returns #701

Open
Open

Description

@TristanIsrael

Hello I am coding a sysmodule under Atmosphère and I have the following issue:

When I call framebufferClose() on a valid FrameBuffer* it never returns. I looked into it and realized that the function nvExit() never returns.

I double-checked the count of framebufferBegin() and framebufferEnd() and they match.

Is there any known issue with framebufferClose()?

Thank you.

Activity

  1. TristanIsrael commented on Dec 19, 2025

    @TristanIsrael
    Author

    I precise I use TransferMemory (tmemCreateFromMemory()) and I call tmemClose() before calling framebufferClose()

  2. masagrator commented on Dec 19, 2025

    @masagrator
    Contributor
     and I call tmemClose() before calling framebufferClose()
    

    You are not supposed to do that. Remove tmemClose() call. nvExit gets stuck because passed TransferMemory is not RW anymore and it expects it to be RW before closing it on its own and returning.

    void _nvCleanup(void) {
        serviceClose(&g_nvSrvClone);
        serviceClose(&g_nvSrv);
        tmemWaitForPermission(&g_nvTransfermem, Perm_Rw);
        tmemClose(&g_nvTransfermem);
    }

    tmemWaitForPermission() is there because passing ownership of Transfermem is async. So in default conditions you cannot be 100% sure it is immediately available after closing service (there were already confirmed cases of race condition). If it can't detect that passed Transfermem is RW, it waits infinitely.

  3. TristanIsrael commented on Dec 19, 2025

    @TristanIsrael
    Author

    Great thank you. I'll fix that.

  4. TristanIsrael commented on Dec 19, 2025

    @TristanIsrael
    Author

    I'm sorry but I removed the call to tmemClose() and the call to framebufferClose() still blocks at the same place. I am using the 4.10.0-1 version of libnx.

  5. TristanIsrael commented on Dec 19, 2025

    @TristanIsrael
    Author

    An additional information, I declared this function

    TransferMemory* g_transfertMemory = nullptr;
    alignas(ams::os::MemoryPageSize) constinit u8 g_nv_transfer_memory[0x80000];
    extern "C" ::Result __nx_nv_create_tmem(TransferMemory *t, u32 *out_size, Permission perm) {
        *out_size = sizeof(g_nv_transfer_memory);
    
        Result rc = tmemCreateFromMemory(t, g_nv_transfer_memory, sizeof(g_nv_transfer_memory), perm);
        
        if(R_SUCCEEDED(rc)) {
            g_transfertMemory = t;
            logDebug("[Renderer] Successfully created transfer memory with permission %i\n", perm);
        } else {
            logError("[Renderer] Could not create transfer memory of size %i and permission %i\n", sizeof(g_nv_transfer_memory), perm);
        }
    
        return rc;
    }
    

    and in my log I can see that Permission == 0, which means Perm_None, maybe that is a problem?

  6. TristanIsrael commented on Dec 19, 2025

    @TristanIsrael
    Author

    Well I fixed this issue by not allocating the Transfer memory by myself and setting u32 __nx_nv_transfermem_size = 0x15000;.

    But now I have different problem... The second time I call framebufferCreate() after the call to framebufferClose(), the result is R_MODULE=345, R_DESCRIPTION=2

    Let me give you more context: I am developing a sysmodule that shows popups and it supposed to work with Tesla overlay for control. But the problem is that both sysmodules can't use VI at the same time. When I don't close the framebuffer and VI Tesla don't show up anymore. That's the reason why I need to close the framebuffer and VI to let Tesla work, and later take it back, and so on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions