From what I can tell `CClientUIInterface::[signal_name]_disconnect` is a no-op.

In other words calling it does *not* disconnect the slot:

For example `uiInterface.NotifyBlockTip_disconnect(BlockNotifyGenesisWait);` in `AppInitMain(...)` does not disconnect `BlockNotifyGenesisWait` as one would expect. The result being that `BlockNotifyGenesisWait` is invoked for every new block :-)

Running `bitcoind` with some debug printing added shows the issue:

```
[signals] CClientUIInterface::ThreadSafeMessageBox_connect(...) entered with 0 connected slots.
[signals] CClientUIInterface::ThreadSafeMessageBox_connect(...) exited with 1 connected slots.
[signals] CClientUIInterface::ThreadSafeQuestion_connect(...) entered with 0 connected slots.
[signals] CClientUIInterface::ThreadSafeQuestion_connect(...) exited with 1 connected slots.
[signals] CClientUIInterface::InitMessage_connect(...) entered with 0 connected slots.
[signals] CClientUIInterface::InitMessage_connect(...) exited with 1 connected slots.
[signals] CClientUIInterface::InitMessage_connect(...) entered with 1 connected slots.
[signals] CClientUIInterface::InitMessage_connect(...) exited with 2 connected slots.
[signals] Calling uiInterface.NotifyBlockTip_connect(&RPCNotifyBlockChange) in OnRPCStarted()
[signals] CClientUIInterface::NotifyBlockTip_connect(...) entered with 0 connected slots.
[signals] CClientUIInterface::NotifyBlockTip_connect(...) exited with 1 connected slots.
[signals] Calling uiInterface.NotifyBlockTip_connect(BlockNotifyGenesisWait) in AppInitMain(...)
[signals] CClientUIInterface::NotifyBlockTip_connect(...) entered with 1 connected slots.
[signals] CClientUIInterface::NotifyBlockTip_connect(...) exited with 2 connected slots.
[signals] RPCNotifyBlockChange(...) was invoked.
[signals] BlockNotifyGenesisWait(...) was invoked.
[signals] Calling uiInterface.NotifyBlockTip_disconnect(BlockNotifyGenesisWait) in AppInitMain(...)
[signals] CClientUIInterface::NotifyBlockTip_disconnect(...) entered with 2 connected slots.
[signals] CClientUIInterface::NotifyBlockTip_disconnect(...) exited with 2 connected slots.
[signals] RPCNotifyBlockChange(...) was invoked.
[signals] BlockNotifyGenesisWait(...) was invoked.
[signals] RPCNotifyBlockChange(...) was invoked.
[signals] BlockNotifyGenesisWait(...) was invoked.
[signals] RPCNotifyBlockChange(...) was invoked.
[signals] BlockNotifyGenesisWait(...) was invoked.
... and so on ...
```

Note how `BlockNotifyGenesisWait(...)` is called also after `uiInterface.NotifyBlockTip_disconnect(BlockNotifyGenesisWait)`.

I think the problem is that the `disconnect(...)` member function of `boost::signals2::signal` expects a function pointer to be passed in (the same that was passed to `.connect(...)`), but we're doing:

```
void CClientUIInterface::signal_name##_disconnect(std::function<signal_name##Sig> fn)
{
    return g_ui_signals.signal_name.disconnect(&fn);
}
```
fs::path pathBootstrap = GetDataDir() / "bootstrap.dat";
    if (fs::exists(pathBootstrap)) {
        FILE *file = fsbridge::fopen(pathBootstrap, "rb");
        if (file) {
            fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
            LogPrintf("Importing bootstrap.dat...\n");
            LoadExternalBlockFile(chainparams, file);
            RenameOver(pathBootstrap, pathBootstrapOld);
        } else {
            LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string());
        }
    }
    
    for (const fs::path& path : vImportFiles) {
        FILE *file = fsbridge::fopen(path, "rb");
        if (file) {
            LogPrintf("Importing blocks file %s...\n", path.string());
            LoadExternalBlockFile(chainparams, file);
        } else {
            LogPrintf("Warning: Could not open blocks file %s\n", path.string());
        }
    }
    
    CValidationState state;
    if (!ActivateBestChain(state, chainparams)) {
        LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state));
        StartShutdown();
        return;
    }