Согласно документации, RTS пытается прервать поток, занятый внешним вызовом, путем отправки ему сигнала SIGPIPE. Так как обработчик, установленный RTS, игнорирует сигнал, единственный эффект состоит в том, что - если поток занят длительным системным вызовом - этот вызов, вероятно, немедленно возвратится с EINTR. Поскольку ваша внешняя функция не проверяет возвратные вызовы printf
и sleep
, чтобы определить, были ли они прерваны, поток весело продолжает свой путь.
Теперь в идеальном мире было бы достаточно изменить вашу функцию для проверки возвращаемых значений, указывающих, что функции были прерваны, например:
void loopForever()
{
for (;;)
{
if (printf("Tick\n") < 0) break;
if (sleep(1) != 0) break;
}
}
К сожалению, интерфейс для sleep()
является braindead - если он прерван, он возвращает количество полных секунд, оставшихся до конца, , а если это ноль - что всегда есть в вашей функции - он возвращает ноль . Вздох ...
Вы можете либо переключиться на usleep
, который разумно вернет -1
в случае прерывания, либо вы можете использовать трюк установки errno
в ноль и проверки, если printf
или sleep
изменить его (на EINTR, но Вы можете также прервать любое ненулевое число):
/* cbits.c */
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include "cbits.h"
void loopForever()
{
errno = 0;
while (!errno)
{
printf("Tick\n");
sleep(1);
}
}
Это должно делать то, что вы хотите.
Теперь, в зависимости от вашего реального случая использования, вам может оказаться более полезным установить обработчик SIGPIPE, особенно если вы ожидаете, что поток будет заблокирован в ходе длительных вычислений (без прерывания каких-либо системных вызовов). Просто обязательно удалите обработчик, когда закончите. Вот пример:
/* cbits.c */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "cbits.h"
volatile sig_atomic_t stop = 0;
void sigpipe_handler()
{
stop = 1;
}
void loopForever()
{
struct sigaction oldact, newact;
bzero(&newact, sizeof(newact));
newact.sa_handler = sigpipe_handler;
sigaction(SIGPIPE, &newact, &oldact);
while (!stop)
{
// loop forever until interrupted
}
printf("Stopped!");
sigaction(SIGPIPE, &oldact, NULL);
}