Прерывание pselect во время ожидания - многопоточность - PullRequest
1 голос
/ 30 марта 2020

Таким образом, согласно руководству, pselect может иметь параметр тайм-аута, и он будет ожидать, если никакие файловые дескрипторы не изменятся. Кроме того, он может быть прерван сигналом:

sigemptyset(&emptyset);    /* Signal mask to use during pselect() */
res = pselect(0, NULL, NULL, NULL, NULL, &emptyset);
if (errno == EINTR) printf("Interrupted by signal\n");

Однако из руководства не очевидно, какие сигналы могут прервать pselect?

Если у меня есть потоки (производители и потребители), и каждый (потребительский) поток использует pselect, есть ли способ прервать только один (потребительский) поток из другого (производящего) потока?

Ответы [ 2 ]

1 голос
/ 31 марта 2020

(Игнорирование всей части вопроса о сигнале и ответ только на

Если у меня есть потоки (производители и потребители), и каждый (потребительский) поток использует pselect, есть ли способ? прервать только один (потребительский) поток из другого (производственного) потока? "

, поскольку заголовок не подразумевает использование сигналов).

Самый простой способ, который я знаю, это чтобы поток раскрыл файловый дескриптор, который всегда будет включен в отслеживаемые дескрипторы p / select, поэтому он всегда отслеживает хотя бы один из них. Если другой поток пишет об этом, вызов p / select вернет:

struct thread {
    pthread_t tid;
    int wake;
    ...
}

void *thread_cb(void *t) {
    struct thread *me = t;
    t->wake = eventfd(0, 0);
    ...
    fd_set readfds;
    // Populate readfds;
    FD_SET(t->wake, &readfds);
    select(...);
}

void interrupt_thread(struct thread *t) {
    eventfd_write(t->wake, 1);
}

Если eventfd недоступен, вы можете заменить его на классический c (и более подробный) канал или другой аналогичный механизм связи.

1 голос
/ 30 марта 2020

Я думаю, что проблема проанализирована в https://lwn.net/Articles/176911/

По этой причине комитет POSIX.1g разработал расширенную версию select(), называется pselect(). Основное различие между select() и pselect() заключается в том, что последний вызов имеет маску сигнала (sigset_t) в качестве дополнительного аргумента:

int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);

pselect использует аргумент sigmask для настройки того, какие сигналы могут его прервать

Набор сигналов, которые в данный момент заблокированы, называется маской сигналов. Каждый процесс имеет свою собственную маску сигналов. Когда вы создаете новый процесс (см. Создание процесса), он наследует маску своего родителя. Вы можете блокировать или разблокировать сигналы с полной гибкостью, изменяя маску сигналов.

источник: https://www.gnu.org/software/libc/manual/html_node/Process-Signal-Mask.html

https://linux.die.net/man/2/pselect

https://www.linuxprogrammingblog.com/code-examples/using-pselect-to-avoid-a-signal-race

В связи с вашими вторыми вопросами есть несколько алгоритмов для синхронизации процесса см., Например, https://www.geeksforgeeks.org/introduction-of-process-synchronization/ и ссылки внизу этой страницы или https://en.wikipedia.org/wiki/Sleeping_barber_problem и связанные страницы. Таким образом, в основном сигналы являются только одним путем для IP C в linux, ср IP C с использованием сигналов на linux

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