I never use sigwait() or sigsuspend() -- I just have signal handlers that write a byte (e.g., the signal number) into a pipe, and maybe they set a global volatile sig_atomic_t variable. DJB calls this a "self-pipe". A self-pipe turns signals into I/O events that select/poll/epoll/event ports/kqueue/io_ring/whatever can handle like any other events.
At exit time I just make sure every thread can get an event. The main thread can pthread_cond_wait() for all the other threads to exit, waiting for the count of them to fall to zero.