I've found some evil bug in my user-level threads library.
My scheduler is actually a singleton class that initializes a signal timer this way:
-
sigAlarm_
is a member field of the scheduler, and its of typestruct sigaction
. -
This is the related part of the scheduler initialization:
sigAlarm_.sa_handler = timerHandlerGlobal; // Assign the first field of sigAlarm (sa_handler) as needed, others zeroed
if (sigaction(SIGVTALRM, &sigAlarm_, nullptr) != 0) { uthreadSystemError("sigaction"); }
Now, this timerHandlerGlobal
is a static function, and not a member function of the scheduler, as C++
doesn't permit passing function members this way.
Now, when I terminate the main thread of the library (which actually runs the scheduler), I'm invoking std::exit(1)
which cleans the resources up.
When I'm running my tests with ASan
(Address Sanitizer
), in some executions, it gets into the timerHandlerGlobal
while the scheduler is already nullptr
! Now, I've been already two days on that, inspecting what's the cause.
Now I see that if I'm adding this ugly condition, no problem appears with ASAN
:
void timerHandlerGlobal(int signo)
{
if (scheduler_manager)
{
scheduler_manager->timerHandler(signo);
}
}
But, why is after std::exit(1)
invoked by the scheduler, the sigaction.sa_handler
(which is timerHandlerGlobal
), is still running? Please tell me you know why it is, I just want to omit this awful condition.
Aucun commentaire:
Enregistrer un commentaire