Я не понимаю поведение pselect. В основном то, что я делаю следующее:pselect уведомляет обе файловые дескрипторы конца файла, хотя только один конец записи был записан на
- Зарегистрировать обработчик сигнала SIGCHILD
- Создание двух труб
- Создать дочерний процесс с помощью вилки
- сна у ребенка в течение 5 секунд, затем exit
- В родительском процессе вызывается pselect, ожидающий на считываемых концах двух труб
- Когда дочерний процесс завершает запись чего-то в первом трубе изнутри обработчик SIGCHILD.
- pselect возвращается в родительский процесс с обоих файловых дескрипторов набор
Я ожидаю выход следующего кода будет:
Pipe1 is set!
Но вместо этого я получаю:
Pipe1 is set!
Pipe2 is set!
Почему оба дескриптора дескриптора конца файла установлены, когда я пишу только в одном конце записи? Является ли это частью поведения нормального pselect уведомления о ложных файловых дескрипторах? Что я делаю не так?
Вот программа:
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include<iostream>
enum PipeEnd {
READ_END = 0, WRITE_END = 1, MAX_END
};
int pipe1[MAX_END], pipe2[MAX_END];
void handle_sigchld(const int signal) {
//In the SIGCHLD handler write the process ID on pipe1
int returnStatus;
int childPID = waitpid(static_cast<pid_t>(-1), &returnStatus, WNOHANG);
write(pipe1[WRITE_END], &childPID, sizeof(childPID));
}
void createPipe(int newPipe[MAX_END]) {
pipe(newPipe);
fcntl(newPipe[READ_END], F_SETFL, O_NONBLOCK);
fcntl(newPipe[WRITE_END], F_SETFL, O_NONBLOCK);
}
int main(int argc, const char** argv) {
//Add a handler for the SIGCHLD signal
struct sigaction sa;
sa.sa_handler = &handle_sigchld;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
sigaction(SIGCHLD, &sa, nullptr);
//Create two pipes
createPipe(pipe1);
createPipe(pipe2);
//Create a child process
if (0 == fork()) {
sleep(5);
exit(0);
}
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(pipe1[READ_END], &read_fds);
FD_SET(pipe2[READ_END], &read_fds);
int maxfd = std::max(pipe1[READ_END], pipe2[READ_END]);
//Wait for a file descriptor to be notified
pselect(maxfd + 1, &read_fds, nullptr, nullptr, nullptr, nullptr);
//Check if the read ends of the two pipes are set/notified
if (FD_ISSET(pipe1[READ_END], &read_fds))
std::cout << "Pipe1 is set!" << std::endl;
if (FD_ISSET(pipe2[READ_END], &read_fds))
std::cout << "Pipe2 is set!" << std::endl;
return 0;
}
Я подозревал, что что-то подобное произошло, когда сигнал был получен в pselect. Большое спасибо! –