Sleep function strange behaviour in signal-driven app - c

for my real-time systems classes i have to do a logging application based on signals. I have one thread, which is waiting in a infinite loop (sem_wait) to receive a specific signal and then it's supposed to create a dumpfile. In the main thread, I'am using sleep function to give me some time for testing until my threads get cancelled and application terminates (i know i could use pthread_join instead of pthread_cancel - it's only for testing).
Apparently, when the main thread goes into sleep and i'm receiving the second dump signal, it looks like sleep goes off and aplication terminates (after the first signal it's okay). When not using the sleep function application works fine. Now i'm wondering what could happen to sleep or maybe i should look for the error somewhere else?
Example code of my app:
int main(){
lib_init(); //here are the threads initialized
sleep(60);
lib_close(); //there we have pthread_cancel;
}
void dump_handler(){
sem_post(&sem);
}
void* dump_thread_fun(void*){
while(1){
sem_wait(&sem);
//dumping happens here
}
}

Related

Trouble using system calls

I have to figure out how to write a programming that loops but cannot be exited using CTRL-C for 5 seconds, but after 5 seconds I can use CTRL-C to end the program. I have been reading up on system calls and what not, but I can't figure out where to start. Here are the exact instructions, if someone could point me in the right direction. Thank you.
Write a C program that uses system calls that creates a loop and cannot be killed with control C for five seconds. When it starts out it prints “I’ve started looping and can’t be killed with ^C. . .” Then every second it prints a message that says “Still looping . . .” After five seconds allow the loop to be killed with control C and display the message “I'm still looping but I can be killed with ^C ...” this is displayed every second until the user kills it.
You want to look at the signal(2) interface. When certain process-related events occur in a UNIX/Linux environment, the operating system will send a signal (essentially a software interrupt) to the process. You can "catch" a signal using the signal function to set a callback function that gets notified when the given signal occurs. For a Ctrl-C you want to look at SIGINT, but there are other signals you can handle with the same interface. As for pausing, that's easy - just use sleep() in a loop.
You can use this one.
void handler(int signo)
{
signal(SIGINT,SIG_DFL);
}
main()
{
signal(SIGINT,SIG_IGN);
signal(SIGALRM,handler);
// your code.
alarm(5);// for 5 seconds.
while(1)
{ sleep(1);
printf("your message\n");
}
}
First ignoring the SIGINT using the singal. And handler for sigalrm. so first 5 seconds ctrl+c will not work. When the sigalrm is found after the ctrl+c will work. So as per your question for particular time period ctrl+c will be stopped.

Multiple independent handlers for threads

I got a problem in C with multiple threads and signal handlers:
The main routine calls multiple loads. Each load has its own controller. The controllers then send signals to pause and resume to their respective loads at different times.
The code of the load looks something like this:
static void signal_handler(int signo) {
/* When signal PAUSE received, get into loop until RESUME arrives */
while (signo != SIGNAL_RESUME) {
/* While in the loop, the main routine gets paused */
sigwait(signalsBetweenControllerandLoad, &signo);
}
}
int load_main() {
signal(SIGNAL_PAUSE, signal_handler);
signal(SIGNAL_RESUME, signal_handler);
while(1) {
/*calculating something */
}
}
The code works when only one load is used. But when multiple loads are running, they start to interfere sometimes. If they do so, the program just freezes at execution. But sometimes the code finishes as expected. The fewer the loads, the higher the possibility that the program works as expected.
Can someone tell me why it does not work? On research I found out that a process (and thus all its child processes) can only have one signal handler active at a time. Is this true?
EDIT: I try to reformulate my main problem: How can I pause / resume the section /*calculating something */ in load_main() at an arbitrary time when I cannot modify this section ("Black box", externally given function)?
Thank you very, very much!
From signal's man page, it mentioned that signal is per-process attribute. So in a multithreaded program, the signal handler is the same for all the threads.
You can try to use semaphore to replace the signal method that you are trying to use. For more detail, you can read the POSIX semaphore man page. It also has example code for your reference.

Persistent signal handling

I'm trying to write a signal handler to catch any number of consecutive SIGINT signals and prevent the program from exiting. The program is a simple file server. The handler sets a global flag which causes the while loop accepting new connections to end, a call to pthread_exit() ensures that main lets current connections finish before exiting. It all goes like clockwork when I hit ctrl-C once but a second time exits the program immediately.
I tried first with signal():
signal(SIGINT, catch_sigint);
...
static void catch_sigint(int signo)
{
...
signal(SIGINT, catch_sigint);
}
I also tried it using sigaction:
struct sigaction sigint_handler;
sigint_handler.sa_handler = catch_sigint;
sigemptyset(&sigint_handler.sa_mask);
sigint_handler.sa_flags = 0;
sigaction(SIGINT, &sigint_handler, NULL);
Unsure how to "reinstall" this one I just duplicated this code in the handler similar to the handler using the signal() method.
Neither one of these works as I expected.
Additional info:
The program is a simple file server. It receives a request from the client which is simply a string consisting of the requested file name. It utilizes pthreads so that transfers can occur simultaneously. Upon receiving SIGINT I wish for the server to exit the while loop and wait for all current transfers to complete then close. As is, no matter how I code the signal handler a second SIGINT terminates the program immediately.
int serverStop = 0;
...
int main()
{
/* set up the server -- socket(), bind() etc. */
struct sigaction sigint_hadler;
sigint_handler.sa_handler = catch_sigint;
sigint_handler.sa_flags = 0;
sigemptyset(&sigint_handler.sa_mask);
sigaction(SIGINT, &sigint_handler, NULL);
/* signal(SIGINT, catch_sigint); */
while(serverStop == 0)
{
/* accept new connections and pthread_create() for each */
}
pthread_exit(NULL);
}
...
static void catch_sigint(int signo)
{
serverStop = 1;
/* signal(SIGINT, catch_sigint) */
}
I don't think any other code could be pertinent but feel free to ask for elaboration
On Linux, you should not have to reinstall the signal handler, using either signal (which implements BSD semantics by default) or sigaction.
when I hit ctrl-C once but a second time exits the program immediately.
That's not because your handler got reset, but likely because your signal handler is doing something it shouldn't.
Here is how I would debug this issue: run the program under GDB and
(gdb) catch syscall exit
(gdb) catch syscall exit_group
(gdb) run
Now wait a bit for the program to start working, and hit Control-C. That will give you (gdb) prompt. Now continue the program as if it has received SIGINT: signal SIGINT (this will invoke your handler). Repeat the 'Control-C/signal SIGINT' sequence again. If you get stopped in either exit or exit_group system call, see where that is coming from (using GDB where command).
Update:
Given the new code you posted, it's not clear exactly where you call pthread_exit to "ensures that main lets current connections finish before exiting". As written, your main thread will exit the loop on first Control-C, and proceed to call exit which would not wait for other threads to finish.
Either you didn't show your actual code, or the "second Control-C" is a red herring and your first Control-C takes you out already (without finishing work in other threads).
NOTE: this is largely guesswork.
I'm pretty sure that calling pthread_exit in the main thread is a bad idea. If the main thread has quit, then the OS may try to send subsequent signals to some other thread.
I recommend that instead of using pthread_exit in the main thread, you just pthread_join() all the other threads, then exit normally.
But it's also important to ensure that the other threads do not get the signals. Normally this is done with sigprocmask (or maybe more correctly pthread_sigmask, which is the same under Linux) to mask the signal out in the worker threads. This ensures that the signal is never delivered to them.
Note that to avoid race conditions, you should use pthread_sigmask in the main thread just before creating a child thread, then set the signal mask back again in the main thread afterwards. This ensures that there is no window, however small, during which a child thread can possibly get unwanted signals.
I'm not sure to understand. A signal handler should usually not re-install any signal handler (including itself), because the signal handler stays in function till another is installed. See also SA_NODEFER flag to sigaction to be able to catch the signal during its handling.
A signal handler should be short. See my answer to this question. It usually mostly sets a volatile sig_atomic_t variable.
What is not working? Don't do complex or long-lasting processing inside signal handlers.
Please show your code...

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

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.

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