c++ – good design for signal handling in main executable

I have a executable that starts up some resources, spins a bunch of worker threads and then waits in a loop for the done command. After the done command is received, it does a bunch of clean up and then exits.

void run()
{
    /* more initialization code, creation of classes, start worker threads etc. */

    while (!done)
    {
        // wait for done command and then exit while 
    }
    
    /* clean up resources */
}

int main(int argc, char * argv())
{
    /* initialization code */
    ...
    
    run()
    ... 
    
    /* clean up code */
    
    return 0;
}

However, when interrupted by a signal like Ctrl + c on Linux, it doesn’t go through the cleanup sequence (neither in run() nor in main())

Now this tutorial shows you how to handle signals by having a function signalHandler for instance that is called on receiving a signal. However, the variables I need to clean up are not in the scope of that function. Also, it seems like duplicated code, since I already have all the clean up stuff in run() and main().

What is a good design approach here? If this was a class, I would just have all the clean up in the destructor, but for a executable with global scope functions like these, I am not sure what’s the best design.

Thank you.