From e6a8d8720982ba6b6e58c71ee002eab1b222e6ca Mon Sep 17 00:00:00 2001 From: mquinson Date: Wed, 10 Oct 2007 15:54:23 +0000 Subject: [PATCH] Do not use recv() but read() to check whether a socket returned by select() is valid to use or good to close. That way, it works not only for real sockets but also for file ones. This implies having a 1-byte-long buffer in the socket for the data we got during this check, and using this micro buffer before the rest of the content in the gras_*_recv() git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@4796 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- src/gras/Transport/rl_transport.c | 21 +++++++-------------- src/gras/Transport/transport.c | 2 +- src/gras/Transport/transport_plugin_file.c | 13 +++++++++---- src/gras/Transport/transport_plugin_tcp.c | 9 ++++++++- src/gras/Transport/transport_private.h | 6 ++++-- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/gras/Transport/rl_transport.c b/src/gras/Transport/rl_transport.c index 7f47f8b635..254e1876ee 100644 --- a/src/gras/Transport/rl_transport.c +++ b/src/gras/Transport/rl_transport.c @@ -151,7 +151,7 @@ gras_socket_t gras_trp_select(double timeout) { THROW3(system_error,EINVAL,"invalid select: nb fds: %d, timeout: %d.%d", max_fds, (int)tout.tv_sec,(int) tout.tv_usec); case ENOMEM: - xbt_assert0(0,"Malloc error during the select"); + xbt_die("Malloc error during the select"); default: THROW2(system_error,errno,"Error during select: %s (%d)", strerror(errno),errno); @@ -182,12 +182,11 @@ gras_socket_t gras_trp_select(double timeout) { accepted->meas = sock_iter->meas; break; - } else if (sock_iter->recv_ok) { + } else { /* Make sure the socket is still alive by reading the first byte */ - char lookahead; int recvd; - recvd = recv(sock_iter->sd, &lookahead, 1, MSG_PEEK); + recvd = read(sock_iter->sd, &sock_iter->recvd_val, 1); if (recvd < 0) { WARN2("socket %d failed: %s", sock_iter->sd, strerror(errno)); /* done with this socket; remove it and break the foreach since it will change the dynar */ @@ -201,20 +200,14 @@ gras_socket_t gras_trp_select(double timeout) { } else { /* Got a suited socket ! */ XBT_OUT; + sock_iter->recvd = 1; _gras_lastly_selected_socket = sock_iter; - /* break sync dynar iteration */ - xbt_dynar_cursor_unlock(sockets); + /* break sync dynar iteration */ + xbt_dynar_cursor_unlock(sockets); return sock_iter; } - - } else { - /* This is a file socket. Cannot recv() on it, but it must be alive */ - XBT_OUT; - _gras_lastly_selected_socket = sock_iter; - xbt_dynar_cursor_unlock(sockets); - return sock_iter; } - + /* if we're here, the socket we found wasn't really ready to be served */ if (ready == 0) { /* exausted all sockets given by select. Request new ones */ diff --git a/src/gras/Transport/transport.c b/src/gras/Transport/transport.c index 41277c1b0e..ad39c5cc31 100644 --- a/src/gras/Transport/transport.c +++ b/src/gras/Transport/transport.c @@ -153,7 +153,7 @@ void gras_trp_socket_new(int incoming, sock->outgoing = incoming ? 0:1; sock->accepting = incoming ? 1:0; sock->meas = 0; - sock->recv_ok = 1; + sock->recvd = 0; sock->valid = 1; sock->moredata = 0; diff --git a/src/gras/Transport/transport_plugin_file.c b/src/gras/Transport/transport_plugin_file.c index de41f4d743..9ad44a7dad 100644 --- a/src/gras/Transport/transport_plugin_file.c +++ b/src/gras/Transport/transport_plugin_file.c @@ -95,7 +95,6 @@ gras_socket_client_from_file(const char*path) { res->sd = 1; /* stdout */ } - res->recv_ok=0; DEBUG5("sock_client_from_file(%s): sd=%d in=%c out=%c accept=%c", path, res->sd, @@ -144,7 +143,6 @@ gras_socket_t gras_socket_server_from_file(const char*path) { res->outgoing?'y':'n', res->accepting?'y':'n'); - res->recv_ok=0; xbt_dynar_push(((gras_trp_procdata_t) gras_libdata_by_id(gras_trp_libdata_id))->sockets,&res); return res; @@ -230,13 +228,20 @@ gras_trp_file_chunk_recv(gras_socket_t sock, xbt_assert0(sock->incoming, "Cannot recv on client file socket"); xbt_assert0(size >= 0, "Cannot receive a negative amount of data"); + if (sock->recvd) { + data[0] = sock->recvd_val; + sock->recvd = 0; + got++; + size--; + } + while (size) { int status = 0; status = read(sock->sd, data+got, (long int)size); DEBUG3("read(%d, %p, %ld);", sock->sd, data+got, size); - if (status == -1) { + if (status < 0) { THROW4(system_error,0,"read(%d,%p,%d) failed: %s", sock->sd, data+got, (int)size, strerror(errno)); @@ -246,7 +251,7 @@ gras_trp_file_chunk_recv(gras_socket_t sock, size -= status; got += status; } else { - THROW0(system_error,0,"file descriptor closed"); + THROW1(system_error,errno,"file descriptor closed after %d bytes",got); } } return got; diff --git a/src/gras/Transport/transport_plugin_tcp.c b/src/gras/Transport/transport_plugin_tcp.c index b8878fdca0..cfce9e2422 100644 --- a/src/gras/Transport/transport_plugin_tcp.c +++ b/src/gras/Transport/transport_plugin_tcp.c @@ -322,6 +322,13 @@ gras_trp_tcp_recv_withbuffer(gras_socket_t sock, int got = 0; + if (sock->recvd) { + data[0] = sock->recvd_val; + sock->recvd = 0; + got++; + bufsize--; + } + while (size>got) { int status = 0; @@ -343,7 +350,7 @@ gras_trp_tcp_recv_withbuffer(gras_socket_t sock, bufsize -= status; got += status; } else { - THROW1(system_error,0,"Socket closed by remote side (got %d bytes before this)", + THROW1(system_error,errno,"Socket closed by remote side (got %d bytes before this)", got); } } diff --git a/src/gras/Transport/transport_private.h b/src/gras/Transport/transport_private.h index 65284420e9..1a042182bb 100644 --- a/src/gras/Transport/transport_private.h +++ b/src/gras/Transport/transport_private.h @@ -58,7 +58,6 @@ typedef struct s_gras_socket { int outgoing :1; /* true if we can write on this sock */ int accepting :1; /* true if master incoming sock in tcp */ int meas :1; /* true if this is an experiment socket instead of messaging */ - int recv_ok :1; /* true if it is valid to recv() on the socket (false if it is a file) */ int valid :1; /* false if a select returned that the peer quitted, forcing us to "close" the socket */ int moredata :1; /* TCP socket use a buffer and read operation get as much data as possible. It is possible that several messages @@ -68,7 +67,10 @@ typedef struct s_gras_socket { don't call select in that case. Note that measurement sockets are not concerned since they use the TCP interface directly, with no buffer. */ - + + int recvd :1; /* true if the recvd_val field contains one byte of the stream (that we peek'ed to check the socket validity) */ + char recvd_val; /* what we peeked from the socket, if any */ + unsigned long int buf_size; /* what to say to the OS. Field here to remember it when accepting */ -- 2.20.1