0

first of all I'd like to apologize for the confusing title. But here's my question:

I have a main function which spawns another thread which is only working from time to time with "sleep(3)" in between.

Inside the main.c , I've a while loop which is running infinitively. So to cancel the program, I have to press Ctrl+C. To catch that, I added a signal handler at the beginning of the main function:

signal(SIGINT, quitProgram);

This is my quitProgram function:

void quitProgram() {  
    printf("CTRL + C received. Quitting.\n");  
    running = 0;  
    return;  
}

So when running == 0, the loop is left.

It all seems to work, at least until the thread mentioned started. When I hit Ctrl+C after the thread has started, I get a strange error message:

`*** longjmp causes uninitialized stack frame `***: ./cluster_control terminated  
======= Backtrace: =========  
/lib/i386-linux-gnu/libc.so.6(+0x68e4e)[0xb7407e4e]  
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x6b)[0xb749a85b]  
/lib/i386-linux-gnu/libc.so.6(+0xfb70a)[0xb749a70a]  
/lib/i386-linux-gnu/libc.so.6(__longjmp_chk+0x42)[0xb749a672]  
./cluster_control[0x8058427]  
[0xb76e2404]  
[0xb76e2428]  
/lib/i386-linux-gnu/libc.so.6(nanosleep+0x46)[0xb7454826]  
/lib/i386-linux-gnu/libc.so.6(sleep+0xcd)[0xb74545cd]  
./cluster_control[0x804c0e6]  
./cluster_control[0x804ae61]  
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb73b8a83]  
./cluster_control[0x804a331]  

When I try to debug it using gdb I get the following:

    `(gdb) where
    `#0  0xb7fdd428 in __kernel_vsyscall ()
    `#1  0xb7d4f826 in nanosleep () at ../sysdeps/unix/syscall-template.S:81
    `#2  0xb7d4f5cd in __sleep (seconds=0) at ../sysdeps/unix/sysv/linux/sleep.c:137
    `#3  0x0804c0e6 in master_main (mastBroad_sock=3, workReady_ptr=0xbffff084) at master.c:150
    `#4  0x0804ae61 in main () at main.c:84

The line 150 in master.c is this:
sleep(PING_PERIOD);

So my guess what's happening: The main thread is exiting while the master_main thread is sleeping and this is causing the error. But: How can I fix this? Is there a better way to let the master_main thread run every few seconds? Or to prevent the main thread from exiting while the master_man is still in sleep?

I tried to use a mutex, but it didn't work (locked the mutex before master_main is sleeping and unlock it afterwards and the exiting main thread needed that mutex to exit).

Additionally I passed an pointer from main to main_master with a state. So I would set the state of main_master to "exit" before exiting the main method, but that didn't work either.

So are there any other ideas? I'm running linux and programming language is C99.

Update 1 Sorry guys, I think I gave you wrong information. The method which causes trouble isn't even inside a thread. Here's an excerpt from my main method:

int main() {
[...]
signal(SIGINT, quitProgram);
while (running)
{
    // if system is the current master
if (master_i)
{
            master_main(mastBroad_sock, &workReady_condMtx);
            pthread_mutex_lock(&(timeCount_mtx_sct.mtx));
            master_i = 0;
            pthread_mutex_unlock(&(timeCount_mtx_sct.mtx));
        }
    [...]
}
return 0;
}

And also an excerpt from the master_main which I guess is the problem.

int master_main(int mastBroad_sock, struct cond_mtx *workReady_ptr) {
[...]
     while (master_i)
     {
          // do something
          sleep(5);   // to perform this loop only every 5 seconds, this is line 150 in master.c
     }
}

Update 2 Forgot to add the code which catches Ctrl+C inside the main.c:

void quitProgram() {
   printf("CTRL + C received. Quitting.\n");
   running = 0;
   return;
}
Marco Hegenberg
  • 612
  • 7
  • 5
  • Check that flag in the thread, too, and terminate when it's set. In the main thread, exit the main loop and join the background thread. It might help if you extracted a minimal example though, as it stands that's missing from your question. – Ulrich Eckhardt Mar 03 '16 at 18:40
  • 1
    Can you provide a code sample? – Mark Segal Mar 03 '16 at 18:58
  • Sure, I added some. And and idea came to my mind. What if I passed the master_main a pointer and change the int the pointer points to inside the quitProgram? So that it can set master_i to 0 when quitting? – Marco Hegenberg Mar 08 '16 at 09:39
  • A full, working code sample would help you, would help us help you, would avoid the messy updates, and might even let you find the problem yourself. – hmijail Mar 08 '16 at 09:53

1 Answers1

1

The simplest solution that comes to mind is to have a global flag that tells the thread that the program is shutting down, and so when the main function want to shutdown it sets the flag and then waits for the thread to terminate. See Joining and Detaching Threads. Depending on what the thread is doing, you might also want to take a look at Condition Variables.

Stuart
  • 1,428
  • 11
  • 20