Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Do not use recv() but read() to check whether a socket returned by select() is valid...
authormquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 10 Oct 2007 15:54:23 +0000 (15:54 +0000)
committermquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Wed, 10 Oct 2007 15:54:23 +0000 (15:54 +0000)
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
src/gras/Transport/transport.c
src/gras/Transport/transport_plugin_file.c
src/gras/Transport/transport_plugin_tcp.c
src/gras/Transport/transport_private.h

index 7f47f8b..254e187 100644 (file)
@@ -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 */
 
index 41277c1..ad39c5c 100644 (file)
@@ -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;
 
index de41f4d..9ad44a7 100644 (file)
@@ -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;
index b8878fd..cfce9e2 100644 (file)
@@ -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);
     }
   }
index 6528442..1a04218 100644 (file)
@@ -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 */