diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2010-12-08 22:54:06 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2010-12-08 22:54:06 +0000 |
commit | 226b067233bc86571f88b1ae67c0c99b3d2b27cc (patch) | |
tree | 311de14131bc7263c4a3e8c1f9ca42db22f95876 | |
parent | 795e0e2046c47c78aead9865a384bc71867b948d (diff) |
in each worker wake up once in a while to check whether any existing LDAP connections should be closed
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1319 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | nslcd/myldap.c | 11 | ||||
-rw-r--r-- | nslcd/myldap.h | 5 | ||||
-rw-r--r-- | nslcd/nslcd.c | 50 |
3 files changed, 54 insertions, 12 deletions
diff --git a/nslcd/myldap.c b/nslcd/myldap.c index 92f0154..89049cc 100644 --- a/nslcd/myldap.c +++ b/nslcd/myldap.c @@ -600,10 +600,7 @@ static void do_close(MYLDAP_SESSION *session) } } -/* This checks the timeout value of the session and closes the connection - to the LDAP server if the timeout has expired and there are no pending - searches. */ -static void myldap_session_check(MYLDAP_SESSION *session) +void myldap_session_check(MYLDAP_SESSION *session) { int i; time_t current_time; @@ -902,8 +899,10 @@ static int do_retry_search(MYLDAP_SEARCH *search) if (nexttry>=endtime) { if (search->session->binddn[0]=='\0') - log_log(LOG_ERR,"no available LDAP server found"); - return rc; + { + log_log(LOG_ERR,"no available LDAP server found: %s",ldap_err2string(rc)); + return LDAP_UNAVAILABLE; + } } /* sleep between tries */ sleeptime=nexttry-time(NULL); diff --git a/nslcd/myldap.h b/nslcd/myldap.h index 0a3bd0b..f7df4a3 100644 --- a/nslcd/myldap.h +++ b/nslcd/myldap.h @@ -76,6 +76,11 @@ void myldap_set_credentials(MYLDAP_SESSION *session,const char *dn, with these searches. This does not close the session. */ void myldap_session_cleanup(MYLDAP_SESSION *session); +/* This checks the timeout value of the session and closes the connection + to the LDAP server if the timeout has expired and there are no pending + searches. */ +void myldap_session_check(MYLDAP_SESSION *session); + /* Close the session and free all the resources allocated for the session. After a call to this function the referenced handle is invalid. */ void myldap_session_close(MYLDAP_SESSION *session); diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c index 8b36732..d6bcc32 100644 --- a/nslcd/nslcd.c +++ b/nslcd/nslcd.c @@ -278,6 +278,7 @@ static void exithandler(void) static int create_socket(void) { int sock; + int i; struct sockaddr_un addr; /* create a socket */ if ( (sock=socket(PF_UNIX,SOCK_STREAM,0))<0 ) @@ -291,6 +292,21 @@ static int create_socket(void) log_log(LOG_DEBUG,"unlink() of "NSLCD_SOCKET" failed (ignored): %s", strerror(errno)); } + /* do not block on accept() */ + if ((i=fcntl(sock,F_GETFL,0))<0) + { + log_log(LOG_ERR,"fctnl(F_GETFL) failed: %s",strerror(errno)); + if (close(sock)) + log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno)); + exit(1); + } + if (fcntl(sock,F_SETFL,i|O_NONBLOCK)<0) + { + log_log(LOG_ERR,"fctnl(F_SETFL,O_NONBLOCK) failed: %s",strerror(errno)); + if (close(sock)) + log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno)); + exit(1); + } /* create socket address structure */ memset(&addr,0,sizeof(struct sockaddr_un)); addr.sun_family=AF_UNIX; @@ -520,6 +536,8 @@ static void *worker(void UNUSED(*arg)) int j; struct sockaddr_storage addr; socklen_t alen; + fd_set fds; + struct timeval tv; /* create a new LDAP session */ session=myldap_create_session(); /* clean up the session if we're done */ @@ -527,20 +545,40 @@ static void *worker(void UNUSED(*arg)) /* start waiting for incoming connections */ while (1) { + /* time out connection to LDAP server if needed */ + myldap_session_check(session); + /* set up the set of fds to wait on */ + FD_ZERO(&fds); + FD_SET(nslcd_serversocket,&fds); + /* set up our timeout value */ + tv.tv_sec=nslcd_cfg->ldc_idle_timelimit; + tv.tv_usec=0; /* wait for a new connection */ - alen=(socklen_t)sizeof(struct sockaddr_storage); - csock=accept(nslcd_serversocket,(struct sockaddr *)&addr,&alen); + j=select(nslcd_serversocket+1,&fds,NULL,NULL,nslcd_cfg->ldc_idle_timelimit>0?&tv:NULL); /* see if we should exit before doing anything else */ if (nslcd_exitsignal!=0) return NULL; + /* check result of select() */ + if (j<0) + { + if (errno==EINTR) + log_log(LOG_DEBUG,"debug: select() failed (ignored): %s",strerror(errno)); + else + log_log(LOG_ERR,"select() failed: %s",strerror(errno)); + continue; + } + /* see if our file descriptor is actually ready */ + if (!FD_ISSET(nslcd_serversocket,&fds)) + continue; + /* wait for a new connection */ + alen=(socklen_t)sizeof(struct sockaddr_storage); + csock=accept(nslcd_serversocket,(struct sockaddr *)&addr,&alen); if (csock<0) { if ((errno==EINTR)||(errno==EAGAIN)||(errno==EWOULDBLOCK)) - { log_log(LOG_DEBUG,"accept() failed (ignored): %s",strerror(errno)); - continue; - } - log_log(LOG_ERR,"accept() failed: %s",strerror(errno)); + else + log_log(LOG_ERR,"accept() failed: %s",strerror(errno)); continue; } /* make sure O_NONBLOCK is not inherited */ |