A bit late to the party, but I just tried #12653 and noticed some non-intuitive behavior (on macOS), that's probably worth explaining release notes and help.

Before this new feature I kept the entire datadir on an SSD drive, so I launch with: `bitcoind -datadir=/Volumes/SSD/Bitcoin`.

Initially I naively moved `/Volumes/SSD/Bitcoin/blocks` to `/Users/bitcoin/blocks` and added a line to `/Volumes/SSD/Bitcoin/bitcoin.conf`: `blocksdir=/Users/bitcoin/blocks`.

I then realized that I shouldn't have moved the `index` subdirectory, so I moved that back to `/Volumes/SSD/Bitcoin/blocks/index`. Having an empty `blocks` dir with just and `index` subdir is a bit weird. Perhaps after @jimpo's #11857 is merged, we could just move / assume all indexes to be there (if `-blocksdir` is set)?

Worse, it created a directory `/Users/bitcoin/blocks/blocks`, which seems like a bug. I had to set `blocksdir=/Users/bitcoin` instead.
try {
        fs::remove(GetPidFile());
    } catch (const fs::filesystem_error& e) {
        LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
    }
#endif
    UnregisterAllValidationInterfaces();
    GetMainSignals().UnregisterBackgroundSignalScheduler();
    GetMainSignals().UnregisterWithMempoolSignals(mempool);
    g_wallet_init_interface.Close();
    globalVerifyHandle.reset();
    ECC_Stop();
    LogPrintf("%s: done\n", __func__);
}
/**
 * Signal handlers are very limited in what they are allowed to do.
 * The execution context the handler is invoked in is not guaranteed,
 * so we restrict handler operations to just touching variables:
 */
#ifndef WIN32
static void HandleSIGTERM(int)
{
    StartShutdown();
}
static void HandleSIGHUP(int)
{
    g_logger->m_reopen_file = true;
}
#else
static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)