Skip to content

Commit

Permalink
[BZ #3242]
Browse files Browse the repository at this point in the history
2007-10-13  Ulrich Drepper  <drepper@redhat.com>
	[BZ #3242]
	* nscd/nscd_helper.c (wait_on_socket): Take timeout as parameter.
	(__readall): If reading failed due to EAGAIN error wait a bit
	and possibly try again.
	(__readvall): Likewise.
  • Loading branch information
Ulrich Drepper committed Oct 13, 2007
1 parent 656f02c commit f714027
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 35 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
2007-10-13 Ulrich Drepper <drepper@redhat.com>

[BZ #3242]
* nscd/nscd_helper.c (wait_on_socket): Take timeout as parameter.
(__readall): If reading failed due to EAGAIN error wait a bit
and possibly try again.
(__readvall): Likewise.

2007-10-13 Bruno Haible <bruno@clisp.org>

* intl/dcigettext.c (_nl_find_msg): Unlock the conversions_lock
Expand Down
103 changes: 68 additions & 35 deletions nscd/nscd_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,63 @@
#include "nscd-client.h"


/* Extra time we wait if the socket is still receiving data. This
value is in microseconds. Note that the other side is nscd on the
local machine and it is already transmitting data. So the wait
time need not be long. */
#define EXTRA_RECEIVE_TIME 200


static int
wait_on_socket (int sock, long int usectmo)
{
struct pollfd fds[1];
fds[0].fd = sock;
fds[0].events = POLLIN | POLLERR | POLLHUP;
int n = __poll (fds, 1, usectmo);
if (n == -1 && __builtin_expect (errno == EINTR, 0))
{
/* Handle the case where the poll() call is interrupted by a
signal. We cannot just use TEMP_FAILURE_RETRY since it might
lead to infinite loops. */
struct timeval now;
(void) __gettimeofday (&now, NULL);
long int end = now.tv_sec * 1000 + usectmo + (now.tv_usec + 500) / 1000;
long int timeout = usectmo;
while (1)
{
n = __poll (fds, 1, timeout);
if (n != -1 || errno != EINTR)
break;

/* Recompute the timeout time. */
(void) __gettimeofday (&now, NULL);
timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000);
}
}

return n;
}


ssize_t
__readall (int fd, void *buf, size_t len)
{
size_t n = len;
ssize_t ret;
do
{
again:
ret = TEMP_FAILURE_RETRY (__read (fd, buf, n));
if (ret <= 0)
break;
{
if (__builtin_expect (ret < 0 && errno == EAGAIN, 0)
/* The socket is still receiving data. Wait a bit more. */
&& wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
goto again;

break;
}
buf = (char *) buf + ret;
n -= ret;
}
Expand All @@ -61,7 +108,15 @@ __readvall (int fd, const struct iovec *iov, int iovcnt)
{
ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt));
if (ret <= 0)
return ret;
{
if (__builtin_expect (ret == 0 || errno != EAGAIN, 1))
/* A genuine error or no data to read. */
return ret;

/* The data has not all yet been received. Do as if we have not
read anything yet. */
ret = 0;
}

size_t total = 0;
for (int i = 0; i < iovcnt; ++i)
Expand All @@ -83,9 +138,17 @@ __readvall (int fd, const struct iovec *iov, int iovcnt)
}
iovp->iov_base = (char *) iovp->iov_base + r;
iovp->iov_len -= r;
again:
r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt));
if (r <= 0)
break;
{
if (__builtin_expect (r < 0 && errno == EAGAIN, 0)
/* The socket is still receiving data. Wait a bit more. */
&& wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
goto again;

break;
}
ret += r;
}
while (ret < total);
Expand Down Expand Up @@ -187,36 +250,6 @@ __nscd_unmap (struct mapped_database *mapped)
}


static int
wait_on_socket (int sock)
{
struct pollfd fds[1];
fds[0].fd = sock;
fds[0].events = POLLIN | POLLERR | POLLHUP;
int n = __poll (fds, 1, 5 * 1000);
if (n == -1 && __builtin_expect (errno == EINTR, 0))
{
/* Handle the case where the poll() call is interrupted by a
signal. We cannot just use TEMP_FAILURE_RETRY since it might
lead to infinite loops. */
struct timeval now;
(void) __gettimeofday (&now, NULL);
long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000;
while (1)
{
long int timeout = end - (now.tv_sec * 1000
+ (now.tv_usec + 500) / 1000);
n = __poll (fds, 1, timeout);
if (n != -1 || errno != EINTR)
break;
(void) __gettimeofday (&now, NULL);
}
}

return n;
}


/* Try to get a file descriptor for the shared meory segment
containing the database. */
static struct mapped_database *
Expand Down Expand Up @@ -265,7 +298,7 @@ get_mapping (request_type type, const char *key,

msg.msg_controllen = cmsg->cmsg_len;

if (wait_on_socket (sock) <= 0)
if (wait_on_socket (sock, 5 * 1000) <= 0)
goto out_close2;

# ifndef MSG_CMSG_CLOEXEC
Expand Down Expand Up @@ -497,7 +530,7 @@ __nscd_open_socket (const char *key, size_t keylen, request_type type,
if (sock >= 0)
{
/* Wait for data. */
if (wait_on_socket (sock) > 0)
if (wait_on_socket (sock, 5 * 1000) > 0)
{
ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
responselen));
Expand Down

0 comments on commit f714027

Please sign in to comment.