Linux: Checking if a socket/pipe is broken without doing a read()/write()

霸气de小男生 提交于 2020-01-01 03:09:10

问题


I have a simple piece of code that periodically writes data to a fd that's passed to it. The fd will most likely be a pipe or socket but could potentially be anything. I can detect when the socket/pipe is closed/broken whenever I write() to it, since I get an EPIPE error (I'm ignoring SIGPIPE). But I don't write to it all the time, and so might not detect a closed socket for a long time. I need to react to the closure asap. Is there a method of checking the fd without having to do a write()? I could then do this periodically if I'm not writing anything.


回答1:


struct pollfd pfd = {.fd = yourfd, .events = POLLERR};
if (poll(&pfd, 1, whatever) < 0) abort();
if (pfd.revents & POLLERR) printf("pipe is broken\n");

This does work for me. Note that sockets are not exactly pipes and thus show different behavior (-> use POLLRDHUP).




回答2:


Try with select and its errorfds parameter:

int **select**(int nfds, fd_set *restrict readfds,
      fd_set *restrict writefds, **fd_set *restrict errorfds**,
      struct timeval *restrict timeout);



回答3:


Nice answers, I like them... I also need to get out of the select habbit and into the (e)poll.

Here's some more traditional methods, if you need them:

/* check whether a file-descriptor is valid */
int fd_valid(int fd)
{   
    if (fcntl(fd, F_GETFL) == -1 && errno == EBADF) return FALSE;
    return TRUE;
}       

This one attempts to duplicate the socket/fd. It a lot simpler than in looks, I left a lot of debug in.

/* 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;
}   


来源:https://stackoverflow.com/questions/9212243/linux-checking-if-a-socket-pipe-is-broken-without-doing-a-read-write

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!