views:

42

answers:

1

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 ?

+1  A: 

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.

nategoose
thanks, this is what I wanted to know. I am talking about catching real signals generated by timers. So i see that you have registered the signal handler in start_func. I thought as the user , I would have to define only the function without writing handler and the library should take care of the rest. Say for example you have a function in your program main () which loops continiously. When your press Ctrl+C , the program halts. Since you have not defined any handler in main, how did it to invoke the handler to kill the thread/process ?
cyrux
If you run a program using your library and send it a SIGINT (Ctrl C) then the whole process gets that because your threading is userspace threading, so you are going to have to have register a signal handler for each signal you are interested in passing on down to your threads, and pass them on down (mark the thread as signaled and ready to run). Then when that thread is about to run you look at the actions that have to be performed for its pending signals. For SIGINT the default action is to kill the process (thread in this case).
nategoose
@cyrux: I realized that you may have been talking about how the signal disposition is initially set up in POSIX. During a fork they stay the same, but during an exec call each one is examined for the special dispositions (ignore, exit, default) and if set to one of those it is left alone, else it is set to the default for that signal.
nategoose