SIG = 41; TID = 2
SIG = 42; TID = 3
SIG = 43; TID = 4
SIG = 41; TID = 2
SIG = 42; TID = 3
SIG = 43; TID = 4
Часто приходится слышать: «…хотелось бы доставить сигнал всем потокам, уведомить всех потребителей и выполнить функцию реакции в каждом потоке…», и именно в такой последовательности действий понимается модель сигналов в потоках при поверхностном с ней ознакомлении. Иногда это представляется очень интересной возможностью, и мы реализуем такую схему взаимодействия в следующем фрагменте (
#include
#include
#include
#include
#include
#include
#include
static void handler(int signo, siginfo_t* info, void* context) {
cout << "SIG = " << signo << ", TID = " << pthread_self() << endl;
}
static void endhandler(int signo) {}
// сигнал, на который реагируют потоки:
const int SIGNUM = SIGRTMIN;
sigset_t sig;
struct threcord {
int tid;
bool noblock;
};
static vector
void* threadfunc(void* data) {
// блокирование всех прочих сигналов:
sigset_t sigall;
sigfillset(&sigall);
SignalProcmask(0, 0, SIG_BLOCK, &sigall, NULL);
// передеспетчеризация для завершения формирования вектора
sched_yield();
tharray[(int)data].noblock =
(SignalProcmask(0, 0, SIG_UNBLOCK, &sig, NULL) != -1);
while (true) {
pause();
tharray[(int)data].noblock =
!(SignalProcmask(0, 0, SIG_BLOCK, &sig, NULL) != 1);
bool nolast = false;
for (vector
i != tharray.end(); i++)
if (nolast = i->noblock) break;
// последовательная пересылка сигнала следующему потоку
if (nolast) kill(getpid(), SIGNUM);
// ... когда пересылать больше некому -
// переинициализация масок
else
for (vector
i != tharray.end(); i++)
i->noblock = (SignalProcmask(0, i->tid, SIG_UNBLOCK, &sig, NULL) != -1);
}
}
int main() {
// переопределение реакции ^C в старой манере
signal(SIGINT, endhandler);
// маска блокирования-разблокирования
sigemptyset(&sig);
sigaddset(&sig, SIGNUM);
// блокировка в главном потоке приложения
sigprocmask(SIG_BLOCK, &sig, NULL);
cout << "Process " << getpid() << ", waiting for signal " << SIGNUM << endl;
// установка обработчика (для дочерних потоков)
struct sigaction act;
act.sa_mask = sig;
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGNUM, &act, NULL) < 0) perror("set signal handler: ");
const int thrnum = 3;
for (int i = 0; i < thrnum; i++) {
threcord threc = { 0, false };
pthread_create(&threc.tid, NULL, threadfunc, (void*)i);
tharray.push_back(three);
}
pause();
// сюда мы попадаем после ^C для завершающих операций...
tharray.erase(tharray.begin(), tharray.end());
cout << "Clean vector" << endl;
}