потоки posix блокируют сигнал и разблокируют

Есть ли способ заблокировать определенные сигналы и разблокировать другие сигналы в том же наборе? Кажется, я просто не могу понять, как это происходит!

Пример

sigset_t set;
sigemptyset(&set);

sigaddset(&set, SIGUSR1);
// Block signal SIGUSR1 in this thread
pthread_sigmask(SIG_BLOCK, &set, NULL);
sigaddset(&set, SIGALRM);
// Listen to signal SIGUSR2
pthread_sigmask(SIG_UNBLOCK, &set, NULL);


pthread_t printer_thread1, printer_thread2;
pthread_create(&printer_thread1, NULL, print, (void *)&f1);
pthread_create(&printer_thread2, NULL, print, (void *)&f2);

bool tl = true;
while(1)
{
    if(tl)
    {
        // thread1 does something
        kill(pid, SIGUSR1);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
    else
    {
        // thread2 does something
        kill(pid, SIGUSR2);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
}

Мне не разрешено использовать только мьютексы, семафоры и т. Д.

Может кто-нибудь помочь? :)

 amaurea29 окт. 2012 г., 02:08
Разве вы не сначала блокируете, а затем разблокируете SIGUSR1 здесь? Во время UNBLOCK набор содержит как SIGUSR1, так и SIGALRM.

Ответы на вопрос(2)

Решение Вопроса

гие сигналы в том же наборе?

С участиемpthread_sigmaskВы можете выбрать:

добавить набор сигналов в набор заблокированных сигналов, используя постояннуюSIG_BLOCKудалить набор сигналов для набора заблокированных сигналов, используя постояннуюSIG_UNBLOCKопределить набор сигналов для блокировки, используя постояннуюSIG_SET

Другими словами, существует текущий набор заблокированных сигналов для потока, и вы можете изменить его, как указано выше, по одной операции за раз.

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

Что касается вашего примера, я полагаю, что вы пытаетесь иметьprinter_thread1 блокSIGUSR2 а такжеSIGALRM, и имеютprinter_thread2 блокSIGUSR1 а такжеSIGALRMи иметь блок основного потокаSIGUSR1 а такжеSIGUSR2, так что каждый поток может отправить сигнал, который будет перехвачен одним потоком (без кодаprint, f1 а такжеf2, невозможно знать наверняка, каково ваше намерение в вашем примере).

Вы должны быть в состоянии достичь этого с помощью следующего кода:

sigset_t set;
pthread_t printer_thread1, printer_thread2;


// Block signal SIGUSR1 & SIGALRM in printer_thread1
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_SET, &set, NULL);
pthread_create(&printer_thread1, NULL, print, (void *)&f1);

// Block signal SIGUSR2 & SIGALRM in printer_thread2
sigaddset(&set, SIGUSR2);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_SET, &set, NULL);
pthread_create(&printer_thread2, NULL, print, (void *)&f2);

// Block signal SIGUSR1 & SIGUSR2 in the main thread
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGUSR2);
// Listen to signal SIGALRM
pthread_sigmask(SIG_SET, &set, NULL);


bool tl = true;
while(1)
{
    if(tl)
    {
        // thread1 does something
        kill(pid, SIGUSR1);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
    else
    {
        // thread2 does something
        kill(pid, SIGUSR2);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
}

посмотрите эти страницы руководства:

pthread_sigmasksigprocmask

для дальнейших деталей.

 the kamilz13 дек. 2018 г., 11:15
правильно ли здесь SET_MASK, я думаю, это должен был быть SIG_SETMASK?
 Max29 окт. 2012 г., 16:12
Спасибо, это имеет смысл, но на самом деле это не работает с потоками принтера. Но я понимаю, как работают маски.

что вы хотите сделать здесь

// Block signal SIGUSR1 in this thread
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &set, NULL);

// Listen to signal SIGALRM
sigemptyset(&set);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);

Набор используется только, чтобы сказать ему, что блокировать или разблокировать. Передав команду, вы можете сбросить ее и создать еще одну маску сигналов. Если вы пропустите набор sigemptyset, набор все равно будет содержать SIGUSR1, который впоследствии будет снова разблокирован. Ну, я думаю, что так оно и есть, по крайней мере - прошло много времени с тех пор, как я использовал сигналы.

Ваш ответ на вопрос