summaryrefslogtreecommitdiff
path: root/nslcd
diff options
context:
space:
mode:
authorTim Harder <radhermit@gmail.com>2014-06-30 15:29:05 -0700
committerArthur de Jong <arthur@arthurdejong.org>2014-07-02 23:01:14 +0200
commit29507979da85db4628993fedfea1c7d174714461 (patch)
tree8733ed2f84365260fd7c73a55668a27cec5c3cc5 /nslcd
parent1765e344b88199e36e79a241b1f0d09aecb9b92a (diff)
Check a socket's connectivity before trying to use it
This alleviates some cases where multi-second lag occurs before a query returns due to some or all connections having been closed by the peer, e.g. a load balancer timing out old connections, but they are all tried before opening new connections. Tested and working on Linux.
Diffstat (limited to 'nslcd')
-rw-r--r--nslcd/myldap.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/nslcd/myldap.c b/nslcd/myldap.c
index 7babe0e..34d23be 100644
--- a/nslcd/myldap.c
+++ b/nslcd/myldap.c
@@ -952,6 +952,10 @@ void myldap_session_check(MYLDAP_SESSION *session)
{
int i;
time_t current_time;
+ int sd;
+ int rc;
+ struct sockaddr sa;
+ socklen_t salen = sizeof(sa);
/* check parameters */
if (session == NULL)
{
@@ -959,19 +963,41 @@ void myldap_session_check(MYLDAP_SESSION *session)
errno = EINVAL;
return;
}
- /* check if we should time out the connection */
- if ((session->ld != NULL) && (nslcd_cfg->idle_timelimit > 0))
+ if (session->ld != NULL)
{
- /* if we have any running searches, don't time out */
- for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
- if ((session->searches[i] != NULL) && (session->searches[i]->valid))
- return;
- /* consider timeout (there are no running searches) */
- time(&current_time);
- if ((session->lastactivity + nslcd_cfg->idle_timelimit) < current_time)
+ rc = ldap_get_option(session->ld, LDAP_OPT_DESC, &sd);
+ if (rc != LDAP_SUCCESS)
{
- log_log(LOG_DEBUG, "myldap_session_check(): idle_timelimit reached");
- do_close(session);
+ myldap_err(LOG_WARNING, session->ld, rc,
+ "ldap_get_option(LDAP_OPT_DESC) failed (ignored)");
+ }
+ else
+ {
+ /* check if the connection was closed by the peer */
+ if (getpeername(sd, &sa, &salen) == -1)
+ {
+ if (errno == ENOTCONN)
+ {
+ log_log(LOG_DEBUG, "myldap_session_check(): connection reset by peer");
+ do_close(session);
+ return;
+ }
+ }
+ }
+ /* check if we should time out the connection */
+ if (nslcd_cfg->idle_timelimit > 0)
+ {
+ /* if we have any running searches, don't time out */
+ for (i = 0; i < MAX_SEARCHES_IN_SESSION; i++)
+ if ((session->searches[i] != NULL) && (session->searches[i]->valid))
+ return;
+ /* consider timeout (there are no running searches) */
+ time(&current_time);
+ if ((session->lastactivity + nslcd_cfg->idle_timelimit) < current_time)
+ {
+ log_log(LOG_DEBUG, "myldap_session_check(): idle_timelimit reached");
+ do_close(session);
+ }
}
}
}