diff options
author | Tim Harder <radhermit@gmail.com> | 2014-07-01 00:29:05 +0200 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2014-07-02 23:01:14 +0200 |
commit | 29507979da85db4628993fedfea1c7d174714461 (patch) | |
tree | 8733ed2f84365260fd7c73a55668a27cec5c3cc5 /nslcd/myldap.c | |
parent | 1765e344b88199e36e79a241b1f0d09aecb9b92a (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/myldap.c')
-rw-r--r-- | nslcd/myldap.c | 48 |
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(¤t_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(¤t_time); + if ((session->lastactivity + nslcd_cfg->idle_timelimit) < current_time) + { + log_log(LOG_DEBUG, "myldap_session_check(): idle_timelimit reached"); + do_close(session); + } } } } |