Pregunta

Background: I understand I can't just call accept() straight away after select() and assume it will work because there is a chance the client might have disconnected after select() returned, even if select() tells me the socket is ready for accept(). Rather, I need to set the socket to O_NONBLOCK and then test for EAGAIN/EWOULDBLOCK when I call accept() - see below.

Question: Do I need to do that same thing with select()/recv()? If select() tells me a socket is ready to read, can I call recv() and guarantee it will not block (or report EAGAIN/EWOULDBLOCK if it's a non-blocking socket)?

Here is the code I'm using for the accept() case:

    while(true) {
        fd_ready = select_for_read(listen_fds, 2);
        fd_client = accept(fd_ready, (struct sockaddr *)&client_addr, &client_addr_len);
        if (fd_client == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                continue;
            } else {
                exit_with_error("Error accepting connection from client");
            }
        }
        break;
    }

(select_for_read takes an array of file descriptors and blocks until one is ready to read using select().)

¿Fue útil?

Solución

From the select man page for Linux:

Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination
has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.

Of course, that warning is in the bugs section, implying that the authors think that isn't an expected behavior -- but nevertheless, under Linux at least it is something that can happen. Personally, I always set my sockets to be non-blocking; that way I don't have to worry about my program accidentally blocking anywhere other than where I intended it to block (i.e. inside select()).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top