- All operation over the unix socket made non-blocking (fix for bug #7774)
authorDaniel Kouřil <kouril@ics.muni.cz>
Thu, 7 Apr 2005 11:56:10 +0000 (11:56 +0000)
committerDaniel Kouřil <kouril@ics.muni.cz>
Thu, 7 Apr 2005 11:56:10 +0000 (11:56 +0000)
- Increased the socket listen queue length (to allow more connections)

org.glite.security.proxyrenewal/interface/renewal.h
org.glite.security.proxyrenewal/project/version.properties
org.glite.security.proxyrenewal/src/api.c
org.glite.security.proxyrenewal/src/common.c
org.glite.security.proxyrenewal/src/renew.c
org.glite.security.proxyrenewal/src/renewal_locl.h
org.glite.security.proxyrenewal/src/renewd.c

index 167b27d..953ab0e 100644 (file)
@@ -40,6 +40,8 @@ typedef enum _edg_wlpr_ErrorCode {
     EDG_WLPR_PROXY_NOT_REGISTERED,
     EDG_WLPR_PROXY_EXPIRED,
     EDG_WLPR_ERROR_VOMS,
+    EDG_WLPR_ERROR_TIMEOUT,
+    EDG_WLPR_ERROR_ERRNO,
 } edg_wlpr_ErrorCode;
 
 /**
index b0ca9c7..4a2125f 100644 (file)
@@ -1,4 +1,4 @@
 
-module.version = 1.0.12
+module.version = 1.0.13
 module.age = 1
                                
index e241f20..922931b 100644 (file)
@@ -13,11 +13,10 @@ static int
 decode_response(const char *msg, const size_t msg_len, edg_wlpr_Response *response);
 
 static int
-do_connect(char *socket_name, int *sock);
+do_connect(char *socket_name, struct timeval *timeout, int *sock);
 
 static int
-send_request(int sock, edg_wlpr_Request *request, edg_wlpr_Response *response);
-
+send_request(int sock, struct timeval *timeout, edg_wlpr_Request *request, edg_wlpr_Response *response);
 
 static int 
 encode_request(edg_wlpr_Request *request, char **msg)
@@ -206,11 +205,14 @@ err:
 }
 
 static int
-do_connect(char *socket_name, int *sock)
+do_connect(char *socket_name, struct timeval *timeout, int *sock)
 {
    struct sockaddr_un my_addr;
    int s;
    int ret;
+   struct timeval before,after,to;
+   int sock_err;
+   socklen_t err_len;
 
    assert(sock != NULL);
    memset(&my_addr, 0, sizeof(my_addr));
@@ -220,13 +222,50 @@ do_connect(char *socket_name, int *sock)
       return errno;
    }
 
+   if (timeout) {
+      int flags = fcntl(s, F_GETFL, 0);
+      if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0)
+        return errno;
+   }
+
    my_addr.sun_family = AF_UNIX;
    strncpy(my_addr.sun_path, socket_name, sizeof(my_addr.sun_path));
 
    ret = connect(s, (struct sockaddr *) &my_addr, sizeof(my_addr));
    if (ret == -1) {
-      close(s);
-      return errno;
+      if (errno == EINPROGRESS) {
+        fd_set fds;
+
+        FD_ZERO(&fds);
+        FD_SET(s, &fds);
+        memcpy(&to, timeout, sizeof(to));
+        gettimeofday(&before,NULL);
+        switch (select(s+1, NULL, &fds, NULL, &to)) {
+           case -1: close(s);
+                    return errno;
+           case 0: close(s);
+                   return EDG_WLPR_ERROR_TIMEOUT;
+        }
+        gettimeofday(&after,NULL);
+        if (edg_wlpr_DecrementTimeout(timeout, before, after)) {
+           close (s);
+           return EDG_WLPR_ERROR_TIMEOUT;
+        }
+
+        err_len = sizeof sock_err;
+        if (getsockopt(s,SOL_SOCKET,SO_ERROR,&sock_err,&err_len)) {
+           close(s);
+           return errno;
+        }
+        if (sock_err) {
+           close(s);
+           errno = sock_err;
+           return errno;
+        }
+      } else {
+        close(s);
+        return errno;
+      }
    }
 
    *sock = s;
@@ -234,7 +273,7 @@ do_connect(char *socket_name, int *sock)
 }
 
 static int
-send_request(int sock, edg_wlpr_Request *request, edg_wlpr_Response *response)
+send_request(int sock, struct timeval *timeout, edg_wlpr_Request *request, edg_wlpr_Response *response)
 {
    int ret;
    char *buf = NULL;
@@ -246,12 +285,12 @@ send_request(int sock, edg_wlpr_Request *request, edg_wlpr_Response *response)
    if (ret)
       return ret;
 
-   ret = edg_wlpr_Write(sock, buf, strlen(buf) + 1);
+   ret = edg_wlpr_Write(sock, timeout, buf, strlen(buf) + 1);
    free(buf);
    if (ret)
       return ret;
 
-   ret = edg_wlpr_Read(sock, &buf, &buf_len);
+   ret = edg_wlpr_Read(sock, timeout, &buf, &buf_len);
    if (ret)
       return ret;
 
@@ -269,14 +308,22 @@ edg_wlpr_RequestSend(edg_wlpr_Request *request, edg_wlpr_Response *response)
    char sockname[1024];
    int ret;
    int sock;
+   struct timeval timeout;
+   const char *s = NULL;
+   double d;
+
+   s = getenv("GLITE_PR_TIMEOUT");
+   d = s ? atof(s) : GLITE_PR_TIMEOUT_DEFAULT;
+   timeout.tv_sec = (long) d;
+   timeout.tv_usec = (long) ((d-timeout.tv_sec) * 1e6);
 
    snprintf(sockname, sizeof(sockname), "%s%d",
            DGPR_REG_SOCKET_NAME_ROOT, getuid());
-   ret = do_connect(sockname, &sock);
+   ret = do_connect(sockname, &timeout, &sock);
    if (ret)
       return ret;
 
-   ret = send_request(sock, request, response);
+   ret = send_request(sock, &timeout, request, response);
 
    close(sock);
    return ret;
@@ -393,6 +440,8 @@ static const char* const errTexts[] = {
    "Proxy not registered",
    "Proxy expired",
    "VOMS error",
+   "Operation timed out",
+   "System error"
 };
 
 const char *
index 87fff76..7b3df64 100644 (file)
 #ident "$Header$"
 
 /* nread() and nwrite() never return partial data */
-static size_t
-nread(int sock, char *buf, size_t buf_len)
+static int
+nread(int sock, struct timeval *to, char *buf, size_t buf_len, size_t *read_len)
 {
    size_t count;
    size_t remain = buf_len;
    char *cbuf = buf;
+   fd_set fds;
+   struct timeval timeout,before,after;
+   int ret;
+
+   if (to) {
+      memcpy(&timeout,to,sizeof(timeout));
+      gettimeofday(&before,NULL);
+   }
 
    while (remain > 0) {
+      FD_ZERO(&fds);
+      FD_SET(sock,&fds);
+      switch (select(sock+1, &fds, NULL, NULL, to ? &timeout : NULL)) {
+        case 0:
+           ret = EDG_WLPR_ERROR_TIMEOUT;
+           goto end;
+        case -1:
+           ret = EDG_WLPR_ERROR_ERRNO;
+           goto end;
+      }
+      
       count = read(sock, cbuf, remain);
       if (count < 0) {
         if (errno == EINTR)
            continue;
-        else
-           return count;
+        else {
+           ret = EDG_WLPR_ERROR_ERRNO;
+           goto end;
+        }
       } else
         if (count == 0) {
-           return count;
+           *read_len = 0;
+           return 0;
         }
       cbuf += count;
       remain -= count;
    }
-   return buf_len;
+   *read_len = buf_len;
+   ret = 0;
+
+end:
+   if (to) {
+      gettimeofday(&after,NULL);
+      edg_wlpr_DecrementTimeout(to, before, after);
+      if (to->tv_sec < 0) {
+        to->tv_sec = 0;
+        to->tv_usec = 0;
+      }
+   }
+
+   return ret;
 }
 
 static size_t
-nwrite(int sock, const char *buf, size_t buf_len)
+nwrite(int sock, struct timeval *to, const char *buf, size_t buf_len)
 {
    const char *cbuf = buf;
    size_t count;
    size_t remain = buf_len;
+   fd_set fds;
+   struct timeval timeout,before,after;
+   int ret;
+
+   if (to) {
+      memcpy(&timeout,to,sizeof(timeout));
+      gettimeofday(&before,NULL);
+   }
 
    while (remain > 0) {
+      FD_ZERO(&fds);
+      FD_SET(sock,&fds);
+      switch (select(sock+1, NULL, &fds, NULL, to ? &timeout : NULL)) {
+        case 0: ret = EDG_WLPR_ERROR_TIMEOUT;
+                goto end;
+        case -1: ret = EDG_WLPR_ERROR_ERRNO;
+                 goto end;
+      }
+                
       count = write(sock, cbuf, remain);
       if (count < 0) {
         if (errno == EINTR)
            continue;
-        else
-           return count;
+        else {
+           ret = EDG_WLPR_ERROR_ERRNO;
+           goto end;
+        }
       }
       cbuf += count;
       remain -= count;
    }
-   return buf_len;
+   ret = buf_len;
+
+end:
+   if (to) {
+      gettimeofday(&after,NULL);
+      edg_wlpr_DecrementTimeout(to, before, after);
+      if (to->tv_sec < 0) {
+        to->tv_sec = 0;
+        to->tv_usec = 0;
+      }
+   }
+
+   return ret;
 }
 
 int
-edg_wlpr_Read(int sock, char **buf, size_t *buf_len)
+edg_wlpr_Read(int sock, struct timeval *timeout, char **buf, size_t *buf_len)
 {
    int ret;
    unsigned char length[4];
+   size_t len;
 
-   ret = nread(sock, length, 4);
-   if (ret == -1) {
+   ret = nread(sock, timeout, length, 4, &len);
+   if (ret) {
       *buf_len = 0;
-      return errno;
+      return ret;
    }
-   if (ret < 4) {
+   if (len != 4) {
       *buf_len = 0;
       return EDG_WLPR_ERROR_UNEXPECTED_EOF; /* XXX vraci i kdyz peer spadne a zavre trubku */
    }
@@ -72,18 +139,21 @@ edg_wlpr_Read(int sock, char **buf, size_t *buf_len)
    if (*buf == NULL)
       return ENOMEM;
 
-   ret = nread(sock, *buf, *buf_len);
-   if (ret != *buf_len) {
+   ret = nread(sock, timeout, *buf, *buf_len, &len);
+   if (ret)
+      return ret;
+
+   if (len != *buf_len) {
       free(*buf);
       *buf_len = 0;
-      return errno;
+      return EDG_WLPR_ERROR_UNEXPECTED_EOF; /* XXX */
    }
 
    return 0;
 }
 
 int
-edg_wlpr_Write(int sock, char *buf, size_t buf_len)
+edg_wlpr_Write(int sock, struct timeval *timeout, char *buf, size_t buf_len)
 {
    unsigned char length[4];
 
@@ -92,8 +162,8 @@ edg_wlpr_Write(int sock, char *buf, size_t buf_len)
    length[2] = (buf_len >> 8)  & 0xFF;
    length[3] = (buf_len >> 0)  & 0xFF;
 
-   if (nwrite(sock, length, 4) != 4 ||
-       nwrite(sock, buf, buf_len) != buf_len)
+   if (nwrite(sock, timeout, length, 4) != 4 ||
+       nwrite(sock, timeout, buf, buf_len) != buf_len)
        return errno;
    
    return 0;
@@ -237,3 +307,17 @@ edg_wlpr_DecodeInt(char *str, int *num)
    *num = atol(str); /* XXX */
    return 0;
 }
+
+int
+edg_wlpr_DecrementTimeout(struct timeval *timeout, struct timeval before, struct timeval after)
+{
+   (*timeout).tv_sec = (*timeout).tv_sec - (after.tv_sec - before.tv_sec);
+   (*timeout).tv_usec = (*timeout).tv_usec - (after.tv_usec - before.tv_usec);
+   while ( (*timeout).tv_usec < 0) {
+      (*timeout).tv_sec--;
+      (*timeout).tv_usec += 1000000;
+   }
+
+   if ( ((*timeout).tv_sec < 0) || (((*timeout).tv_sec == 0) && ((*timeout).tv_usec == 0)) ) return(1);
+   else return(0);
+}
index 39113cc..ddae37b 100644 (file)
@@ -76,6 +76,8 @@ load_proxy(const char *cur_file, X509 **cert, EVP_PKEY **priv_key,
    ret = 0;
    
 end:
+   if (proxy)
+      globus_gsi_cred_handle_destroy(proxy);
    if (result)
       ret = EDG_WLPR_ERROR_GENERIC;
 
index 0eb94e4..9d0774d 100644 (file)
@@ -69,6 +69,8 @@ typedef enum {
 
 #define DGPR_RETRIEVE_DEFAULT_HOURS 10
 
+#define GLITE_PR_TIMEOUT_DEFAULT       120
+
 typedef struct {
   char *version;
   edg_wlpr_Command command;
@@ -112,10 +114,10 @@ edg_wlpr_StoreToken(char **buf, size_t *buf_len, char *command,
                     char *value, const char *separator);
 
 int
-edg_wlpr_Read(int sock, char **buf, size_t *buf_len);
+edg_wlpr_Read(int sock, struct timeval *timeout, char **buf, size_t *buf_len);
 
 int
-edg_wlpr_Write(int sock, char *buf, size_t buf_len);
+edg_wlpr_Write(int sock, struct timeval *timeout, char *buf, size_t buf_len);
 
 void
 edg_wlpr_CleanRequest(edg_wlpr_Request *request);
@@ -135,4 +137,7 @@ edg_wlpr_DecodeInt(char *str, int *num);
 int
 edg_wlpr_RequestSend(edg_wlpr_Request *request, edg_wlpr_Response *response);
 
+int
+edg_wlpr_DecrementTimeout(struct timeval *timeout, struct timeval before, struct timeval after);
+
 #endif /* RENEWAL_LOCL_H */
index cd2bef8..4a595a8 100644 (file)
@@ -18,6 +18,7 @@ char *key = NULL;
 char *vomsconf = NULL;
 
 static volatile int die = 0, child_died = 0;
+double default_timeout = 0;
 
 static struct option opts[] = {
    { "help",       no_argument,       NULL,  'h' },
@@ -114,11 +115,15 @@ proto(int sock)
    edg_wlpr_Response  response;
    edg_wlpr_Request  request;
    command_table  *command;
+   struct timeval timeout;
 
    memset(&request, 0, sizeof(request));
    memset(&response, 0, sizeof(response));
 
-   ret = edg_wlpr_Read(sock, &buf, &buf_len);
+   timeout.tv_sec = (long) default_timeout;
+   timeout.tv_usec = (long) ((default_timeout - timeout.tv_sec) * 1e6);
+
+   ret = edg_wlpr_Read(sock, &timeout, &buf, &buf_len);
    if (ret) {
       edg_wlpr_Log(LOG_ERR, "Error reading from client: %s",
                    edg_wlpr_GetErrorString(ret));
@@ -150,7 +155,7 @@ proto(int sock)
    if (ret)
       goto end;
 
-   ret = edg_wlpr_Write(sock, buf, strlen(buf) + 1);
+   ret = edg_wlpr_Write(sock, &timeout, buf, strlen(buf) + 1);
    free(buf);
    if (ret) {
       edg_wlpr_Log(LOG_ERR, "Error sending response to client: %s",
@@ -171,15 +176,7 @@ doit(int sock)
    int newsock;
    struct sockaddr_un client_addr;
    int client_addr_len = sizeof(client_addr);
-#if 0
-   next_renewal = LONG_MAX;
-   size_of_proxies = PROXIES_ALLOC_SIZE;
-   proxies = malloc((size_of_proxies) * sizeof(struct guarded_proxy *));
-   if (proxies == NULL) {
-       return ENOMEM;
-   }
-   proxies[0] = NULL;
-#endif
+   int flags;
 
    while (!die) {
 
@@ -204,6 +201,14 @@ doit(int sock)
       }
       edg_wlpr_Log(LOG_DEBUG, "Got connection");
 
+      flags = fcntl(newsock, F_GETFL, 0);
+      if (fcntl(newsock, F_SETFL, flags | O_NONBLOCK) < 0) {
+        edg_wlpr_Log(LOG_ERR, "Can't set O_NONBLOCK mode (%s), closing.\n",
+                     strerror(errno));
+        close(newsock);
+        continue;
+      }
+        
       proto(newsock);
 
       edg_wlpr_Log(LOG_DEBUG, "Connection closed");
@@ -458,7 +463,7 @@ do_listen(char *socket_name, int *sock)
       return errno;
    }
 
-   ret = listen(s, 5); /* XXX enough ? */
+   ret = listen(s, 50);
    if (ret == -1) {
       edg_wlpr_Log(LOG_ERR, "listen(): %s", strerror(errno));
       close(s);
@@ -519,6 +524,7 @@ int main(int argc, char *argv[])
    int   ret;
    pid_t pid;
    struct sigaction    sa;
+   const char *s = NULL;
 
    progname = strrchr(argv[0],'/');
    if (progname) progname++; 
@@ -578,6 +584,9 @@ int main(int argc, char *argv[])
    if (cadir)
       setenv("X509_CERT_DIR", cadir, 1);
 
+   s = getenv("GLITE_PR_TIMEOUT");
+   default_timeout = s ? atof(s) : GLITE_PR_TIMEOUT_DEFAULT;
+
    memset(&sa,0,sizeof(sa));
    sa.sa_handler = catchsig;
    sigaction(SIGINT,&sa,NULL);