aboutsummaryrefslogtreecommitdiff
path: root/nscd
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-01-31 23:24:54 +0000
committerUlrich Drepper <drepper@redhat.com>2007-01-31 23:24:54 +0000
commit58a2d52e95b8c38ce43dcfbd6cce1d1ca1196c61 (patch)
tree6f62c97d4269494a69da57ba925262d08a857f39 /nscd
parent8f9bf732964b3a239d2d0b2d772d65dc717eb0da (diff)
downloadglibc-58a2d52e95b8c38ce43dcfbd6cce1d1ca1196c61.zip
glibc-58a2d52e95b8c38ce43dcfbd6cce1d1ca1196c61.tar.gz
glibc-58a2d52e95b8c38ce43dcfbd6cce1d1ca1196c61.tar.bz2
* nscd/nscd_helper.c (open_socket): Now takes request type and key
as parameter. Construct request record. Try sending request before the first poll use, it usually succeeds. Adjust all callers. * nscd/nscd-client.h: Define MAXKEYLEN.
Diffstat (limited to 'nscd')
-rw-r--r--nscd/nscd_helper.c124
1 files changed, 72 insertions, 52 deletions
diff --git a/nscd/nscd_helper.c b/nscd/nscd_helper.c
index 336adfe..394b2f8 100644
--- a/nscd/nscd_helper.c
+++ b/nscd/nscd_helper.c
@@ -97,16 +97,20 @@ __readvall (int fd, const struct iovec *iov, int iovcnt)
static int
-open_socket (void)
+open_socket (request_type type, const char *key, size_t keylen)
{
int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
return -1;
+ struct
+ {
+ request_header req;
+ char key[keylen];
+ } reqdata;
+
/* Make socket non-blocking. */
- int fl = __fcntl (sock, F_GETFL);
- if (fl != -1)
- __fcntl (sock, F_SETFL, fl | O_NONBLOCK);
+ __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
@@ -115,13 +119,56 @@ open_socket (void)
&& errno != EINPROGRESS)
goto out;
- struct pollfd fds[1];
- fds[0].fd = sock;
- fds[0].events = POLLOUT | POLLERR | POLLHUP;
- if (__poll (fds, 1, 5 * 1000) > 0)
- /* Success. We do not check for success of the connect call here.
- If it failed, the following operations will fail. */
- return sock;
+ reqdata.req.version = NSCD_VERSION;
+ reqdata.req.type = type;
+ reqdata.req.key_len = keylen;
+
+ memcpy (reqdata.key, key, keylen);
+
+ bool first_try = true;
+ struct timeval tvend;
+ while (1)
+ {
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+ ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
+ sizeof (reqdata),
+ MSG_NOSIGNAL));
+ if (__builtin_expect (wres == (ssize_t) sizeof (reqdata), 1))
+ /* We managed to send the request. */
+ return sock;
+
+ if (wres != -1 || errno != EAGAIN)
+ /* Something is really wrong, no chance to continue. */
+ break;
+
+ /* The daemon is busy wait for it. */
+ int to;
+ if (first_try)
+ {
+ gettimeofday (&tvend, NULL);
+ tvend.tv_sec += 5;
+ to = 5 * 1000;
+ first_try = false;
+ }
+ else
+ {
+ struct timeval now;
+ gettimeofday (&now, NULL);
+ to = ((tvend.tv_sec - now.tv_sec) * 1000
+ + (tvend.tv_usec - now.tv_usec) / 1000);
+ }
+
+ struct pollfd fds[1];
+ fds[0].fd = sock;
+ fds[0].events = POLLOUT | POLLERR | POLLHUP;
+ if (__poll (fds, 1, to) <= 0)
+ /* The connection timed out or broke down. */
+ break;
+
+ /* We try to write again. */
+ }
out:
close_not_cancel_no_status (sock);
@@ -181,36 +228,15 @@ get_mapping (request_type type, const char *key,
int saved_errno = errno;
int mapfd = -1;
+ char resdata[keylen];
- /* Send the request. */
- struct
- {
- request_header req;
- char key[keylen];
- } reqdata;
-
- int sock = open_socket ();
+ /* Open a socket and send the request. */
+ int sock = open_socket (type, key, keylen);
if (sock < 0)
goto out;
- reqdata.req.version = NSCD_VERSION;
- reqdata.req.type = type;
- reqdata.req.key_len = keylen;
- memcpy (reqdata.key, key, keylen);
-
-# ifndef MSG_NOSIGNAL
-# define MSG_NOSIGNAL 0
-# endif
- if (__builtin_expect (TEMP_FAILURE_RETRY (__send (sock, &reqdata,
- sizeof (reqdata),
- MSG_NOSIGNAL))
- != sizeof (reqdata), 0))
- /* We cannot even write the request. */
- goto out_close2;
-
/* Room for the data sent along with the file descriptor. We expect
the key name back. */
-# define resdata reqdata.key
struct iovec iov[1];
iov[0].iov_base = resdata;
iov[0].iov_len = keylen;
@@ -423,28 +449,22 @@ int
__nscd_open_socket (const char *key, size_t keylen, request_type type,
void *response, size_t responselen)
{
+ /* This should never happen and it is something the nscd daemon
+ enforces, too. He it helps to limit the amount of stack
+ used. */
+ if (keylen > MAXKEYLEN)
+ return -1;
+
int saved_errno = errno;
- int sock = open_socket ();
+ int sock = open_socket (type, key, keylen);
if (sock >= 0)
{
- request_header req;
- req.version = NSCD_VERSION;
- req.type = type;
- req.key_len = keylen;
-
- struct iovec vec[2];
- vec[0].iov_base = &req;
- vec[0].iov_len = sizeof (request_header);
- vec[1].iov_base = (void *) key;
- vec[1].iov_len = keylen;
-
- ssize_t nbytes = TEMP_FAILURE_RETRY (__writev (sock, vec, 2));
- if (nbytes == (ssize_t) (sizeof (request_header) + keylen)
- /* Wait for data. */
- && wait_on_socket (sock) > 0)
+ /* Wait for data. */
+ if (wait_on_socket (sock) > 0)
{
- nbytes = TEMP_FAILURE_RETRY (__read (sock, response, responselen));
+ ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
+ responselen));
if (nbytes == (ssize_t) responselen)
return sock;
}