From a9af1b0795c4a75f8919d7a87491fe7ab041b272 Mon Sep 17 00:00:00 2001 From: mquinson Date: Tue, 1 Aug 2006 00:27:53 +0000 Subject: [PATCH 1/1] Fix a vicious bug: TCP socket use a buffer and read operation get as much data as possible. It is possible that several messages are received in one shoot, and select won't catch them afterward again. Instead, the select will block and the surnumerous messages are lost. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@2671 48e7efb5-ca39-0410-a469-dd3cf9ba447f --- src/gras/Transport/rl_transport.c | 11 +++++++++-- src/gras/Transport/transport.c | 1 + src/gras/Transport/transport_plugin_tcp.c | 2 ++ src/gras/Transport/transport_private.h | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/gras/Transport/rl_transport.c b/src/gras/Transport/rl_transport.c index 6d65d78340..b10be517b2 100644 --- a/src/gras/Transport/rl_transport.c +++ b/src/gras/Transport/rl_transport.c @@ -42,7 +42,12 @@ gras_socket_t gras_trp_select(double timeout) { gras_socket_t sock_iter; /* iterating over all sockets */ int cursor; /* iterating over all sockets */ - + /* Check whether there is more data to read from the socket we selected last time. + This can happen with tcp buffered sockets since we try to get as much data as we can for them */ + static gras_socket_t _lastly_selected_socket = NULL; + if (_lastly_selected_socket && _lastly_selected_socket->moredata) + return _lastly_selected_socket; + /* Compute FD_SETSIZE */ #ifdef HAVE_SYSCONF fd_setsize = sysconf( _SC_OPEN_MAX ); @@ -59,7 +64,7 @@ gras_socket_t gras_trp_select(double timeout) { now = gras_os_time(); DEBUG2("wakeup=%f now=%f",wakeup, now); if (now == -1 || now >= wakeup) { - /* didn't find anything */ + /* didn't find anything; no need to update _lastly_selected_socket since its moredata is 0 (or we would have returned it directly) */ THROW1(timeout_error,0, "Timeout (%f) elapsed with selecting for incomming connexions", timeout); @@ -182,12 +187,14 @@ gras_socket_t gras_trp_select(double timeout) { } else { /* Got a suited socket ! */ XBT_OUT; + _lastly_selected_socket = sock_iter; return sock_iter; } } else { /* This is a file socket. Cannot recv() on it, but it must be alive */ XBT_OUT; + _lastly_selected_socket = sock_iter; return sock_iter; } diff --git a/src/gras/Transport/transport.c b/src/gras/Transport/transport.c index 476780fefc..aff786ee31 100644 --- a/src/gras/Transport/transport.c +++ b/src/gras/Transport/transport.c @@ -160,6 +160,7 @@ void gras_trp_socket_new(int incoming, sock->meas = 0; sock->recv_ok = 1; sock->valid = 1; + sock->moredata = 0; sock->sd = -1; sock->port = -1; diff --git a/src/gras/Transport/transport_plugin_tcp.c b/src/gras/Transport/transport_plugin_tcp.c index a4db1b640a..b92dccc722 100644 --- a/src/gras/Transport/transport_plugin_tcp.c +++ b/src/gras/Transport/transport_plugin_tcp.c @@ -338,6 +338,8 @@ gras_trp_tcp_recv_withbuffer(gras_socket_t sock, got); } } + /* indicate to the gras_select function that there is more to read on this socket so that it does not actually select */ + sock->moredata = (bufsize != 0); return got; } diff --git a/src/gras/Transport/transport_private.h b/src/gras/Transport/transport_private.h index a2d50dc7a2..9b384ecc29 100644 --- a/src/gras/Transport/transport_private.h +++ b/src/gras/Transport/transport_private.h @@ -42,6 +42,9 @@ typedef struct s_gras_socket { 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 are received in one shoot, and select won't catch them afterward again. + This boolean indicates that this is the case, so that we don't call select in that case. */ unsigned long int buf_size; /* what to say to the OS. field here to remember it when accepting */ -- 2.20.1