summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2010-12-08 22:54:06 +0000
committerArthur de Jong <arthur@arthurdejong.org>2010-12-08 22:54:06 +0000
commit226b067233bc86571f88b1ae67c0c99b3d2b27cc (patch)
tree311de14131bc7263c4a3e8c1f9ca42db22f95876
parent795e0e2046c47c78aead9865a384bc71867b948d (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.c11
-rw-r--r--nslcd/myldap.h5
-rw-r--r--nslcd/nslcd.c50
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 */