Как избавиться от ошибки при выходе из pthread, когда он находится в режиме сна()?

Прежде всего, я хотел бы извиниться за запутанный заголовок. Но вот мой вопрос:

У меня есть основная функция, которая порождает другой поток, который время от времени работает только с «сном (3)» между ними.

Внутри main.c у меня есть цикл while, который работает бесконечно. Итак, чтобы отменить программу, я должен нажать Ctrl + C. Чтобы уловить это, я добавил обработчик сигнала в начале основной функции:

signal(SIGINT, quitProgram);

Это моя функция quitProgram:

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

Итак, когда running == 0, петля остается.

Кажется, все работает, по крайней мере, до тех пор, пока не началась упомянутая тема. Когда я нажимаю Ctrl+C после запуска потока, я получаю странное сообщение об ошибке:

`*** 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

Строка 150 в master.c такова:
sleep(PING_PERIOD);

Итак, я предполагаю, что происходит: основной поток завершается, пока поток master_main спит, и это вызывает ошибку. Но: Как я могу это исправить? Есть ли лучший способ запускать поток master_main каждые несколько секунд? Или предотвратить выход основного потока, пока master_man все еще спит?

Я пытался использовать мьютекс, но это не сработало (заблокировал мьютекс до того, как master_main спит, и разблокировал его после этого, а выходящий основной поток нуждался в этом мьютексе для выхода).

Кроме того, я передал указатель с main на main_master с состоянием. Поэтому я бы установил состояние main_master на «выход» перед выходом из основного метода, но это тоже не сработало.

Так есть еще идеи? У меня линукс и язык программирования C99.

Обновление 1 Извините, ребята, кажется, я дал вам неверную информацию. Метод, вызывающий проблемы, даже не находится внутри потока. Вот выдержка из моего основного метода:

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;
}

А также выдержка из master_main, которая, я думаю, является проблемой.

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
     }
}

Обновление 2 Забыли добавить код, который ловит Ctrl+C внутри main.c:

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

person Marco Hegenberg    schedule 03.03.2016    source источник
comment
Также проверьте этот флаг в потоке и завершите работу, когда он будет установлен. В основном потоке выйти из основного цикла и присоединиться к фоновому потоку. Это может помочь, если вы извлечете минимальный пример, поскольку он отсутствует в вашем вопросе.   -  person Ulrich Eckhardt    schedule 03.03.2016
comment
Можете ли вы предоставить образец кода?   -  person Mark Segal    schedule 03.03.2016
comment
Конечно, я добавил кое-что. И идея пришла мне в голову. Что, если я передам master_main указатель и изменю int, на который указывает указатель внутри quitProgram? Чтобы он мог установить master_i в 0 при выходе?   -  person Marco Hegenberg    schedule 08.03.2016
comment
Полный работающий образец кода поможет вам, поможет нам помочь вам, позволит избежать беспорядочных обновлений и, возможно, даже позволит вам самостоятельно найти проблему.   -  person hmijail mourns resignees    schedule 08.03.2016


Ответы (1)


Самое простое решение, которое приходит на ум, — это иметь глобальный флаг, сообщающий потоку, что программа завершает работу, поэтому, когда функция main хочет завершить работу, она устанавливает флаг и затем ждет завершения потока. См. раздел присоединение и отсоединение потоков. В зависимости от того, что делает поток, вы также можете взглянуть на переменные условия.

person Stuart    schedule 03.03.2016
comment
Я уже пробовал это, но либо я сделал ошибку, либо это не работает. - person Marco Hegenberg; 04.03.2016