From 58765607905fee397de9fffedf517c06d05d50ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Kou=C5=99il?= Date: Mon, 4 Apr 2005 14:56:45 +0000 Subject: [PATCH] All operation over the unix socket made nonblocking so they can't block forever --- .../interface/renewal.h | 2 + .../project/version.properties | 2 +- org.glite.security.proxyrenewal/src/api.c | 71 ++++++++++-- org.glite.security.proxyrenewal/src/common.c | 126 +++++++++++++++++---- org.glite.security.proxyrenewal/src/renewal_locl.h | 9 +- org.glite.security.proxyrenewal/src/renewd.c | 31 +++-- 6 files changed, 195 insertions(+), 46 deletions(-) diff --git a/org.glite.security.proxyrenewal/interface/renewal.h b/org.glite.security.proxyrenewal/interface/renewal.h index 167b27d..953ab0e 100644 --- a/org.glite.security.proxyrenewal/interface/renewal.h +++ b/org.glite.security.proxyrenewal/interface/renewal.h @@ -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; /** diff --git a/org.glite.security.proxyrenewal/project/version.properties b/org.glite.security.proxyrenewal/project/version.properties index e6702aa..1864e41 100644 --- a/org.glite.security.proxyrenewal/project/version.properties +++ b/org.glite.security.proxyrenewal/project/version.properties @@ -1,4 +1,4 @@ #Wed Jan 12 04:00:08 CET 2005 -module.version=1.1.4 +module.version=1.2.1 module.build=137 module.age=1 diff --git a/org.glite.security.proxyrenewal/src/api.c b/org.glite.security.proxyrenewal/src/api.c index e241f20..922931b 100644 --- a/org.glite.security.proxyrenewal/src/api.c +++ b/org.glite.security.proxyrenewal/src/api.c @@ -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 * diff --git a/org.glite.security.proxyrenewal/src/common.c b/org.glite.security.proxyrenewal/src/common.c index 87fff76..7b3df64 100644 --- a/org.glite.security.proxyrenewal/src/common.c +++ b/org.glite.security.proxyrenewal/src/common.c @@ -3,63 +3,130 @@ #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); +} diff --git a/org.glite.security.proxyrenewal/src/renewal_locl.h b/org.glite.security.proxyrenewal/src/renewal_locl.h index 0eb94e4..9d0774d 100644 --- a/org.glite.security.proxyrenewal/src/renewal_locl.h +++ b/org.glite.security.proxyrenewal/src/renewal_locl.h @@ -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 */ diff --git a/org.glite.security.proxyrenewal/src/renewd.c b/org.glite.security.proxyrenewal/src/renewd.c index cd2bef8..a672210 100644 --- a/org.glite.security.proxyrenewal/src/renewd.c +++ b/org.glite.security.proxyrenewal/src/renewd.c @@ -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"); @@ -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); -- 1.8.2.3