diff options
author | Ulrich Drepper <drepper@redhat.com> | 2007-01-31 23:24:54 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2007-01-31 23:24:54 +0000 |
commit | 58a2d52e95b8c38ce43dcfbd6cce1d1ca1196c61 (patch) | |
tree | 6f62c97d4269494a69da57ba925262d08a857f39 /nscd/nscd_helper.c | |
parent | 8f9bf732964b3a239d2d0b2d772d65dc717eb0da (diff) | |
download | glibc-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/nscd_helper.c')
-rw-r--r-- | nscd/nscd_helper.c | 124 |
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; } |