等待时中断 pselect - 多线程

Interrupting pselect when it's waiting - multithread

因此,根据手册,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,有没有办法从另一个(生产者)线程中断一个(消费者)线程?

我认为问题在https://lwn.net/Articles/176911/

中得到了分析

For this reason, the POSIX.1g committee devised an enhanced version of select(), called pselect(). The major difference between select() and pselect() is that the latter call has a signal mask (sigset_t) as an additional argument:

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

pselect 使用 sigmask 参数来配置哪些信号可以中断它

The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.

来源: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/ and the links down on this page or https://en.wikipedia.org/wiki/Sleeping_barber_problem and associated pages. So basically signals are only one path for IPC in linux, cf IPC using Signals on linux

(忽略问题的所有信号部分,只回答

If I have threads (producers and consumers), and each (consumer)thread is using pselect, is there a way to interrupt only one (consumer)thread from another(producer) thread?"

,因为标题并不暗示信号的使用)。

我知道的最简单的方法是让线程公开一个文件描述符,该文件描述符将始终包含在 p/select 受监视的描述符中,因此它始终至少监视一个。如果其他线程写入,p/select 调用将 return:

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,您可以将其替换为经典(且更冗长)的管道或其他类似的通信机制。