Adding signal handler to a function in C for a thread library - c

I am writing a basic user level thread library. The function prototype for thread creation is
thr_create (start_func_pointer,arg)
{
make_context(context_1,start_func)
}
start_func will be user defined and can change depending on user/program
once after creation of thread, if I start executing it using
swapcontext(context_1,context_2)
the function start_func would start running. Now , if a signal comes in , I need to handle it. Unfortunately, I just have the handle to start_func so I cant really define signal action inside the start_func
is there a way I can add a signal handling structure inside the start_function and point it to my code. something like this
thr_create (start_func_pointer,arg)
{
start_func.add_signal_hanlding_Structure = my_signal_handler();
make_context(context_1,start_func)
}
Does anybody know how posix does it ?

If you are talking about catching real signals from the actual operating system you are running on I believe that you are going to have to do this application wide and then pass the signals on down into each thread (more on this later). The problem with this is that it gets complicated if two (or more) of your threads are trying to use alarm which uses SIGALRM -- when the real signal happens you can catch it, but then who do you deliver it to (one or all of the threads?).
If you are talking about sending and catching signals just among the threads within a program using your library then sending a signal to a thread would cause it to be marked ready to run, even if it were waiting on something else previously, and then any signal handling functionality would be called from your thread resume code. If I remember from your previous questions you had a function called thread_yield which was called to allow the next thread to run. If this is the case then thread_yield needs to check a list of pending signals and preform their actions before returning to where ever thread_yield was called (unless one of the signal handlers involved killing the current thread, in which case you have to do something different).
As far as how to implement registering of signal handlers, in POSIX that is done by system calls made by the main function (either directly or indirectly). So you could have:
static int foo_flag = 0;
static void foo_handle(int sig) {
foo_flag = 1;
}
int start_func(void * arg) {
thread_sig_register(SIGFOO, foo_handle);
thread_pause();
// this is a function that you could write that would cause the current thread
// to mark itself as not ready to run and then call thread_yield, so that
// thread_pause() will return only after something else (a signal) causes the
// thread to become ready to run again.
if (foo_flag) {
printf("I got SIGFOO\n");
} else {
printf("I don't know what woke me up\n");
}
return 0;
}
Now, from another thread you can send this thread a SIGFOO (which is just a signal I made up for demonstration purposes).
Each of your thread control blocks (or whatever you are calling them) will have to have a signal handler table (or list, or something) and a pending signal list or a way to mark the signals as pending. The pending signals will be examined (possibly in some priority based order) and the handler action is done for each pending signal before returning to that threads normal code.

Related

Making yield function with timer in C

I want to write a code to switch between threads every 10 microseconds.
But the problem is in the yield function. I get an interrupt while running the timer handler. So it doesn't finish properly.
This is the code I have for initializing the timer:
signal(SIGALRM, &time_handler);
struct itimerval t1;
t1.it_interval.tv_sec = INTERVAL_SEC;
t1.it_interval.tv_usec = INTERVAL_USEC;
t1.it_value.tv_sec = INTERVAL_SEC;
t1.it_value.tv_usec = INTERVAL_USEC;
setitimer(ITIMER_REAL, &t1, NULL);
And this is the code for the handler function:
void time_handler(int signo)
{
write(STDOUT_FILENO, "interrupt\n", sizeof("interrupt\n"));
green_yield();
}
And this is what I do in the yield function: a queue from which we get the thread to run next. The problem is at any moment before I swap context between threads, I can get an interrupt. Especially because I swap the context at the end of this function.
int green_yield(){
green_t *susp = running ;
// add susp to ready queue
// ===========================
enQueue(ready_queue, susp);
// ===========================
// select the next thread for execution
// ===========================
green_t * next = deQueue(ready_queue);
running = next;
// ===========================
// save current state into susp->context and switch to next->context
// ===========================
swapcontext(susp->context, next->context);
return 0;}
What can I do to make sure that I first complete the yield function and then get the interrupt?
Foreword: Depending on your system hardware, a write() system call into stdout may take longer than 10 us. So, calling this from the SIGALRM handler with a cyclic timer of 10 us may be wrong.
In GLIBC, signal(SIGALRM, time_handler) is equivalent to sigaction() with SA_RESTART flag. SIGALRM signal is blocked during the execution of the handler. So, you will not receive a signal while running the handler. It is implicitly blocked during handler execution and unblocked after it finishes. Since the latter calls green_yield(), you will not get a signal while running inside green_yield().
As getcontext() saves the signal mask with SIGALRM unblocked (as I guess you call it at the beginning of your program when you create the threads), when you swap the context to go from one interrupted threads running the signal handler to the next schedulable thread, the newly running thread:
At 1st scheduling time, returns from its getcontext() (the thread creation point). This restores the signal mask even if the previous thread did not return from the signal handler because the context contains a signal mask with SIGALRM unblocked. When the timer elapses again, SIGALRM will come again to interrupt the newly running thread which will yield the CPU in the signal handler calling swapcontext(). This time the saved context contains a signal mask with a blocked SIGALRM;
At subsequent scheduling time, returns from swapcontext() as it was interrupted by the signal and so was running the end of the signal handler. The context restores a blocked SIGALRM signal but this will be unblocked as part of the execution of the signal handler since its execution restarts from the end of the signal handler.
Even if the preceding is supposed to work, note that when a signal is raised, the system creates a stack frame on the top of the current process stack to make the signal handler appear as a function called by the user program and returning at the interruption point. This frame on the stack must not be corrupted by threads running from any point on the global process stack. The use of sigaltstack() may be considered (see notes below).
What about your thread implementation? They all share the same stack (the process stack). When you create them, they all save their context with getcontext() nearly at the same point in the global process stack. So, when you switch from one thread to another, the newly running thread may screw up the stack frames of the previously running threads... I think this is the point on which you should focus: arrange your threads to make them run with their own global stack zone or with their own stack using something like makecontext(). The manual of the latter provides an example to create several threads of execution with separate stacks.
Side note:
swapcontext() is not part of the allowed function calls in the signal handlers: cf. man 7 signal-safety. So, it is not safe to call it from there. But at the same time, we can see that non-local gotos (i.e. longjmp()) can safely be called from the signal handler. Since swapcontext() looks like a non local goto, it may be safe to call it under the same conditions as longjmp()...
The manual of sigaltstack() provides some tips to use swapcontext() from signal handlers

Starting a thread from inside an interrupt handler

I'm trying to start a thread as soon as an interrupt occurs. However, I have realized that I can't start a thread from within an interrupt handler (or any function that is directly or indirectly being called by the interrupt handler). So, what I have decided to do is have the handler assert a flag. Then, a separate thread continously monitors that flag and if it's asserted it will in turn create (and start) a thread. Here's a pseudocode:
int interrupt_flag = 0;
interrupt_handler(void)
{
interrupt_flag = 1
}
monitoring_thread(void) //this thread is started at the start of the program
{
while(1)
{
if(interrupt_flag)
{
interrupt_flag = 0;
//start the thread here
sleep(/*some amount of time*/);
}
}
}
I'm not really happy with having a dedicated while loop constantly monitoring a flag. The problem with this is that it significantly reduces the speed of the other threads in my program. For this reason, I'm calling the sleep function to increase the speed of the other threads in my program.
Question: Is there a way I can truly start a thread upon interrupt, without having a dedicated while loop? Is there a workaround for starting a thread from within an interrupt handler?
If it makes any difference, I'm using the POSIX library.
Thanks,
PS. This question is somewhat related to an earlier question posted here:
Sharing data between master thread and slave thread in interrupt driven environment in C
Instead of having your monitoring thread spin on a flag, it could wait until the interrupt handler provides notification that a thread should be spawned. One way to do this is with a semaphore:
sem_t interrupt_sem;
void interrupt_handler(void)
{
sem_post(&interrupt_sem);
}
void monitoring_thread(void)
{
while(1)
{
sem_wait(&interrupt_sem);
//start the thread here
}
}
Previously, I had a solution based on a condition variable, but it is unlikely your system would operate correctly if the interrupt handler makes blocking calls. It could cause a deadlock or other undefined behaviors, as the variables in the system may not have consistent values at the time the interrupt takes place.
As pointed out in comments by myself and others, your operating system should provide some kind of interface to explicitly wake up a waiting task. In the code above, we are assuming the monitoring thread is always active in the background.
you can use POSIX semaphore too
you can wait a semaphore that initial value is 0 by a thread that will be blocked by wait
and post this semaphore in your signal handle function
then , thread above will be waked up and do things you want(create thread)

halting a client server program

I am sorry for the basicness of this question, but I am having an issue here. I have a client-server program. I don't know before hand how many connections will come but they are not infinite. And at the end , after all connections are closed some results are output. But the problem I am having is, accepting connections is in an infinite while loop, how is it stoppedd to output the result.
Thanks
you need to have some form of condition to break out of you loop, in your case, a timeout would probably work the best, basically meaning, if you don't get any new clients for x seconds, you stop looking for clients, same goes for any for of connection error.
Anything more requires looking at the code you are using.
Handling EINTR on error from accept(2) with terminating the program and hitting ^C usually works.
You could install a handler for the SIGTERM signal which would set a global volatile sig_atomic_t variable, and test that variable in your multiplexing loop (probably around poll or select). Remember that signal handlers cannot call many functions (only the async-signal-safe ones).
Catching nicely SIGTERM is expected from most Linux or Posix servers.
You could consider using an event handling library like libev, libevent etc.
Although my background is with Windows NT the function "names" are ones that name generic threading or process functions that should be available in any multi-threading environment.
If the main thread can determine when the child thread in question should terminate it can either do this by having the child thread loop on a boolean - such as "terminate_conditon" - or by terminating the thread throught its handle.
// child thread
terminate_condition=FALSE;
while (!terminate_condition)
{
// accept connections
}
child_thread_done=TRUE;
// output results
exit_thread ();
// main thread
child_thread_done=FALSE;
child_thread=create_thread (...);
// monitor connections to determine when done
terminate_condition=TRUE;
while (!child_thread_done)
{
sleep (1);
}
// or maybe output results here?
exit_process ();
This controlled termination solution requires that only one thread writes to the child_thread_done boolean and that any other thread only reads.
Or
// child thread
while (1)
{
// accept connections
}
// main thread
child_thread=create_thread (...);
// monitor connections to determine when done
kill_thread (child_thread);
// output results
exit_process ();
The second form is messier since it simply kills the child thread. In general it is better to have the child thread perform a controlled termination, especially if it has allocated resources (which become the responsibility of the process as a whole rather than just the allocating thread).
If there are many child threads working with connections a synchronized termination mechanism is necessary: either a struct with as many members as there are child threads (a terminating thread sets its "terminated" boolean to true, terminates and the main thread monitors the struct to make sure all child "terminated" booleans are true before proceeding) or a counter containing the number of child threads operating (when a child is about to terminate it takes exclusive control of the counter via a spinlock, decrements it and frees the lock before terminating: the main thread doesn't do anything before the counter contains zero).

pthreads: How to handle signals in a main thread that creates other threads? (specific code shown)

I have a main thread, which stays in the main function, i.e. I do not create it specifically as in pthread_create, because it's not necessary. This thread opens a file, then creates other threads, waits for them to finish their work (i.e., does the join), cleans up everything (pointers, semaphores, conditional variables and so on...).
Now, I have to apply this code to block SIGINT:
sigset_t set;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGINT);
pthread_sigmask(SIG_BLOCK, &set, NULL);
while (1) {
sigwait(&set, &sig);
switch (sig) {
case SIGINT:
/* handle interrupts */
break;
default:
/* unexpected signal */
pthread_exit((void *)-1);
}
}
and it says You must use the main() function to launch the N+1 threads and wait for their completion. If a SIGINT signal arrives at the program it should be handled by the main thread in order to shutdown the program and its threads a clean way
My doubt is how should I put this code? Is it wrong to put it on a background thread created in main() ? Because I already have a cicle, with an exit flag, that creates and join all the other threads, so I don't understand if this code goes exactly to the main function where all is done/called to initiate the program. If I put it on a thread, with this code and the handler to clean, is this considerated as busy waiting?
"It says"? What says? The homework assignment?
The first thing you should understand about programming with threads and signals is that you have very little control over which thread a signal is delivered to. If your main thread wants to be the one to get the signal, it should block the signal before creating any new threads and possible unblock it after it finishes creating them, to ensure that the signal is not delivered to them.
However, if you're following best practices for signal handlers, it probably doesn't matter which thread handles the signal. All the signal handler should do is set a global flag or write a byte to a pipe (whichever works best to get the main thread to notice that the signal happened. (Note that you cannot use condition variables or any locking primitives from signal handlers!) As in the code fragment in your question, blocking the signal and using sigwait is also possible (be aware, again, that it needs to be blocked in all threads), but most programs can't afford to stop and wait just for signals; they need to wait for condition variables and/or input from files as well. One way to solve this issue is to make a dedicated thread to call sigwait, but that's rather wasteful. A better solution, if you're already using select, would be to switch to pselect that can wait for signals as well as file descriptor events (at the same time).
Rather than asking us for the answers (which would be hard to give anyway without seeing the full program you're trying to make this work with), you'd be much better off trying to really understand the intricacies of signals with threads.

How to properly handle signals when using the worker thread pattern?

I have a simple server that looks something like this:
void *run_thread(void *arg) {
// Communicate via a blocking socket
}
int main() {
// Initialization happens here...
// Main event loop
while (1) {
new_client = accept(socket, ...);
pthread_create(&thread, NULL, &run_thread, *thread_data*);
pthread_detach(thread);
}
// Do cleanup stuff:
close(socket);
// Wait for existing threads to finish
exit(0);
)
Thus when a SIGINT or SIGTERM is received I need to break out of the main event loop to get to the clean up code. Moreover most likely the master thread is waiting on the accept() call so it's not able to check some other variable to see if it should break;.
Most of the advice I found was along the lines of this: http://devcry.blogspot.com/2009/05/pthreads-and-unix-signals.html (creating a special signal handling thread to catch all the signals and do processing on those). However, it's the processing portion that I can't really wrap my head around: how can I possibly tell the main thread to return from the accept() call and check on an external variable to see if it should break;?
Usually I am waiting on select(listeninig-socket-here) not on accept(). accept() is usually a method where a program doesn't spend lots of time waiting. And when I wait in select() and the signal SIGTERM is sent to that thread (in your case it is the main thread) I exit from that select and select returns interrupted system call .
I second skwllsp in his opinion that you should be using select call instead of accept. But, my additional suggestion is that you follow the advice of the blog whose link you have posted and create a seperate signal handling thread and ignore signals in all other threads. Then when the signal is received in the signal handling thread, use pthread_cancel to cancel the other threads. When you use pthread_cancel, if the thread which is being cancelled is in cancellation point (select happens to be one), it will come out and enter into your handler and you can cleanup and exit the thread.
You can find more info on this here, here and here

Resources