Mam prosty fragment kodu, który okresowo zapisuje dane na fd, które zostały do niego przesłane. Fd najprawdopodobniej będzie fajką lub gniazdem, ale potencjalnie może być cokolwiek. Mogę wykryć, kiedy gniazdo/potok jest zamknięty/zepsuty, gdy piszę() do niego, ponieważ dostaję błąd EPIPE (ignoruję SIGPIPE). Ale nie piszę do niego przez cały czas, więc może nie wykryć zamkniętego gniazda przez długi czas. Muszę zareagować na zamknięcie jak najszybciej. Czy istnieje metoda sprawdzania fd bez konieczności pisania()? Mogłem wtedy robić to okresowo, jeśli nic nie piszę.Linux: Sprawdzanie, czy gniazdo/rura jest zepsute bez robienia odczytu()/zapisu()
Odpowiedz
struct pollfd pfd = {.fd = yourfd, .events = POLLERR};
if (poll(&pfd, 1, whatever) < 0) abort();
if (pfd.revents & POLLERR) printf("pipe is broken\n");
To działa na mnie. Zauważ, że gniazda nie są dokładnie rurami, a zatem wykazują inne zachowanie (-> użyj POLLRDHUP).
Aha! Miałem literówkę i sprawdzałem wydarzenia w drodze powrotnej, a nie na nowo. Wielkie dzięki, to działało świetnie. – gimmeamilk
Świetna odpowiedź. Jestem zbyt przyzwyczajony do wywoływania select(). Muszę definitywnie próbować ewoluować w tym punkcie. +1 –
spróbować z select i jej errorfds parametru:
int **select**(int nfds, fd_set *restrict readfds,
fd_set *restrict writefds, **fd_set *restrict errorfds**,
struct timeval *restrict timeout);
Dzięki, ale próbowałem dodać moje fd do zestawu wyjątków i nie mogłem zmusić go do zachowania się inaczej, gdy rura była zepsuta. (To może działać dobrze z gniazdem, nie próbowałem jeszcze, ponieważ moja obecna konfiguracja daje mi fajkę) – gimmeamilk
Dobre odpowiedzi, lubię je ... Muszę też wyjść z wybranego habbitu i zagłębić się w ankietę (e).
Oto kilka tradycyjnych metod, jeśli trzeba je:
/* check whether a file-descriptor is valid */
int fd_valid(int fd)
{
if (fcntl(fd, F_GETFL) == -1 && errno == EBADF) return FALSE;
return TRUE;
}
Ten próbuje powielić Socket/FD. To dużo prostsze niż w wyglądzie, zostawiłem dużo debugowania w.
/* check a file descriptor */
int fd_check(int i) {
int fd_dup = dup(i);
if (fd_dup == -1) {
strcpy(errst, strerror(errno));
// EBADF oldfd isn’t an open file descriptor, or newfd is out of the allowed range for file descriptors.
// EBUSY (Linux only) This may be returned by dup2() during a race condition with open(2) and dup().
// EINTR The dup2() call was interrupted by a signal; see signal(7).
// EMFILE The process already has the maximum number of file descriptors open and tried to open a new one.
if (errno == EBADF) {
return FALSE;
}
return TRUE;
}
close(fd_dup);
return TRUE;
}
select, sonda, i epoll będzie wszystko wam –
Dzięki za odpowiedź, ale nie jestem pewien, jak do tej pracy z Kobza. Próbowałem wywołania select() z moim fd w zapisie i oprócz fdsets, a wynik połączenia nie zmienia się, gdy potok jest zepsuty (zawsze zwracaj moje fd w zestawie zapisu). Próbowałem również poll() z wszystkimi ustawionymi zdarzeniami i znowu nie ma różnicy. – gimmeamilk
Nie przesuwaj swojego fd do fdsets zapisu. Tylko oprócz jednego. –