Exiting a pthread normally, by returning from its procedure, or calling exit(0) for the main thread doesn't run pthread_exit and doesn't call cleanup handlers, avoiding that situation.
exit() should only be called when the last thread terminates (and with the right status code of course). There shouldn't be anything special about the main thread.