Use a dedicated thread to process signals #105
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
KittenSquad/glewlwyd!105
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "signal-thread"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
I put the signal handling in a dedicated thread which should be able to use malloc/logging/... without causing problems. (See #103)
Handling SIGSGEV/SIGILL/SIGBUS is implemented but likely pointless: If a thread runs into an instruction that triggers one of those it will be impossible for the thread to continue even though the signal is blocked for the thread. The kernel will the quickly kill the program despite the blocked signal, most likely before the signal thread gets a chance to run.
I made
close_signalsstatic to make sure it doesn't go out of scope while the signal thread might still be running.I prefer either to declare functions in
glewlwyd.hor implement them above the calling function. In this case I think declaringsignal_threadinglewlwyd.hwill be sufficient and in harmony with the code style.@ -56,2 +56,4 @@pthread_t signal_thread_id;static sigset_t close_signals;if (config == NULL) {Why is this variable static? Is it to be invisible in the other files?
@ -181,15 +183,27 @@ int main (int argc, char ** argv) {pthread_cond_init(&global_handler_close_cond, NULL)) {y_log_message(Y_LOG_LEVEL_ERROR, "init - Error initializing global_handler_close_lock or global_handler_close_cond");}I think we should test the result of
sigemptysetandsigaddsetto be 0, just to be sureI'm not sure putting an infinite loop here is relevant. If I understand this function correctly, it waits until an expected signal is sent, then broadcasts a closing signal with
global_handler_close_condor exits if the signal is bad.In any case, when the signal is received, it will close the program, or there may be other
signumvalues?If we need to keep the
while (1) {, then I'd add ausleep(50)right before the end loop to avoid having the CPU at 100%.Here I'd replace the
y_log_message(Y_LOG_LEVEL_ERRORwithfprintf(stderrbecausey_log_message'smallocmay cause other problems during a program failure.Wow, thanks @sth for the help! I really appreciate the initiative.
I made some comments, nothing big but some questions and ways to make the code cleaner.
Practically there won't be other signum values, because we only wait for signals in
sigsand we check for all of them manually. All signals we receive will end up exiting the thread (and program) in some way, so the infinite loop is not really needed.It would be useful if there were other signals that would be handled without exiting (typical would be "reload configuration on SIGHUP" or something like that). Then we really should continue to wait for the more signal that might come. I'll add a log warning for any unexpected received signals, even though it should never happen currently. It's a bit more resilient in case more signals are added later. But the loop could also be removed if you prefer it.
I don't think a sleep is really necessary: if there are signals generated at a rate that takes 100% CPU to process, than the real problem is wherever those signals are generated. The thread processing them can't really be blamed that many of them are coming in.
@ -56,2 +56,4 @@pthread_t signal_thread_id;static sigset_t close_signals;if (config == NULL) {I made it static because a pointer to it is passed to the signal thread and I wasn't sure if that thread might still be alive (for a short time) after the local variables in main() go out of scope.
We currently don't explicitly stop that thread before exiting main. Doing so would probably be more correct, but actually won't help anyway because the program exits by calling
exit(), not by returning from main. I'm not sure if in this case it's guaranteed that other threads are cleaned up before local variables inmain()might be overwritten. If the variable isstaticit definitely is valid until program exit.Yeah, makes sense to keep it simple in these cases.
@ -181,15 +183,27 @@ int main (int argc, char ** argv) {pthread_cond_init(&global_handler_close_cond, NULL)) {y_log_message(Y_LOG_LEVEL_ERROR, "init - Error initializing global_handler_close_lock or global_handler_close_cond");}Definitely!
Then I would remove the while loop
@ -1518,22 +1532,35 @@ void print_help(FILE * output) {* handles signal catch to exit properly when ^C is used for exampleSome indentation to improve here
@ -1518,22 +1532,35 @@ void print_help(FILE * output) {* handles signal catch to exit properly when ^C is used for exampleAnd same as below, use
fprintfbefore an emergency exit.Also, I think we should detach the thread to release its resource when it finishes.
no, apparently you don't need to detach this thread, my bad