devkitPro/libctru

srvEnableNotification causes ctrulib to hang on exit

Swiftloke opened this issue · 2 comments

Consider the following code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <3ds.h>
 
int main(int argc, char* argv[])
{
    gfxInitDefault();
    consoleInit(GFX_TOP, NULL);
 
    printf("Hello, world!\n");
    srvInit();
    Handle notifsemaphore;
    srvEnableNotification(&notifsemaphore);
 
    // Main loop
    while (aptMainLoop())
    {
        gspWaitForVBlank();
        gfxSwapBuffers();
        hidScanInput();
 
        // Your code goes here
        u32 kDown = hidKeysDown();
        if (kDown & KEY_START)
            break; // break in order to return to hbmenu
    }
    printf("Exiting");
    svcCloseHandle(notifsemaphore);
 
    gfxExit();
    return 0;
}

This simple program takes, from a rough "Mississippi" timer, about 18.5 seconds to exit. Commenting out srvEnableNotification allows an exit as fast as you would expect. In a practical application it varies. I haven't seen it go any further than a whole minute, but some testers have complained that it takes several minutes to exit (???)
Doing some debugging, I found the following information about this hang, as provided through the following GDB info:

Thread 1 stopped.
svcSleepThread () at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/svc.s:88
88      in /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/svc.s
(gdb) backtrace
#0  svcSleepThread () at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/svc.s:88
#1  0x00129be4 in aptExit () at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/services/apt.c:300
#2  0x0012c12c in __appExit ()
    at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/system/appExit.c:15
#3  0x001000f8 in __ctru_exit ()
    at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/system/stack_adjust.s:39
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) thread 2
[Switching to thread 2 (Thread 390)]
#0  svcWaitSynchronizationN () at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/svc.s:271
271     in /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/svc.s
(gdb) backtrace
#0  svcWaitSynchronizationN () at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/svc.s:271
#1  0x001295f8 in aptEventHandler (arg=<optimized out>)
    at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/services/apt.c:331
#2  0x00125694 in _thread_begin (arg=<optimized out>)
    at /home/davem/projects/devkitpro/pacman-packages/libctru/src/source/thread.c:37
#3  0x00000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

These are the only two threads still alive, everything else has closed out. After talking with profi200 and yellows8 on IRC we couldn't figure anything out, which leads me to conclude that this is a bug in libctru. Here are the logs: https://pastebin.com/GxAaPvSq

fincs commented

I don't see how this could possibly be a libctru bug. To me it looks like some conflict between SRV notifications and APT (quite unsurprisingly). I'm not sure SRV notifications are meant to be used by anything other than sysmodules. It might help to look at the source code of the sm sysmodule for clues.

TuxSH commented

Not a bug, it's how PM works.

Look at this code: https://github.com/LumaTeam/Luma3DS/blob/master/sysmodules/pm/source/termination.c#L102

If you don't have notifications enabled, PM will kill your process ASAP, otherwise it'll wait until timeout. If you do have notifications enabled, you're supposed to handle notification 0x100 (termination notification which you don't have to subscribe to).

It looks like APT is using a 20s timeout.