int newsock = accept (sock,(struct sockaddr *) &clientname,&size);
if (newsock < 0)
{
- if (errno == EAGAIN)
+ // return on non-fatal errors (list taken from man-page)
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ECONNABORTED || errno == EINTR ||
+ errno == EMFILE || errno == ENFILE || errno == ENOBUFS || errno == ENOMEM ||
+ errno == EPROTO || errno == EPERM || errno == ETIMEDOUT)
{
- LOGSTREAM(error,"accept error (EAGAIN): no connection waiting");
+ LOGSTREAM(error,"non-fatal accept error: " << strerror(errno));
return;
}
- /* default: break */
- EXCEPTIONSTREAM(error,t2n_server_error,"error accepting connection: " << strerror(errno));
+ /* fatal error: will usually kill or restart the server */
+ EXCEPTIONSTREAM(error,t2n_server_error,"fatal error accepting connection: " << strerror(errno));
}
FD_SET (newsock, &connection_set);
return;
}
-bool socket_server::fill_buffer(long long usec_timeout)
+/** @brief look for new connections and new data in any of the existing connections
+ @param usec_timeout wait until new data is found, max timeout usecs.
+ -1: wait endless
+ 0: return instantly
+ @param usec_timeout_remaining if non-NULL the function will write the
+ not used time to the given target
+ @retval true if new data was found (does not mean that the received data
+ is a complete packet though)
+*/
+bool socket_server::fill_buffer(long long usec_timeout,long long* usec_timeout_remaining)
{
fd_set used_fdset=connection_set;
int ret=select (FD_SETSIZE, &used_fdset, NULL, NULL, timeout_ptr);
+ // return the timeout we did not use
+ if (usec_timeout > 0 && usec_timeout_remaining != NULL)
+ *usec_timeout_remaining=(tval.tv_sec*1000000)+tval.tv_usec;
+
if (ret < 0)
{
if (errno == EINTR)
std::map<unsigned int, server_connection*>::iterator ie=connections.end();
for(std::map<unsigned int, server_connection*>::iterator i=connections.begin(); i != ie; i++)
if (!i->second->server_connection::is_closed())
- if (i->second->fill_buffer(0))
- data_found=true;
+ {
+ // shutdown all connections which throw exceptions to protect the server
+ try
+ {
+ if (i->second->fill_buffer(0))
+ data_found=true;
+ }
+ catch (t2n_transfer_error &e)
+ { i->second->close(); }
+ catch(...)
+ { throw; }
+ }
return data_found;
}