Commit dbdc79f9 authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

ITS#5836

parent ba20225e
......@@ -8,6 +8,7 @@ OpenLDAP 2.4.17 Engineering
Fixed liblutil for _GNU_SOURCE (ITS#5464,ITS#5666)
Added slapd sasl auxprop support (ITS#6147)
Added slapd schema checking tool (ITS#6150)
Added slapd writetimeout keyword (ITS#5836)
Fixed slapd assert with closing connections (ITS#6111)
Fixed slapd cert validation (ITS#6098)
Fixed slapd errno handling (ITS#6037)
......
......@@ -450,7 +450,9 @@ along with this option.
.B olcIdleTimeout: <integer>
Specify the number of seconds to wait before forcibly closing
an idle client connection. A setting of 0 disables this
feature. The default is 0.
feature. The default is 0. You may also want to set the
.B olcWriteTimeout
option.
.TP
.B olcIndexIntLen: <integer>
Specify the key length for ordered integer indices. The most significant
......@@ -753,11 +755,12 @@ The default is 16; the minimum value is 2.
Specify the maximum number of threads to use in tool mode.
This should not be greater than the number of CPUs in the system.
The default is 1.
.\"ucdata-path is obsolete / ignored...
.\".TP
.\".B ucdata-path <path>
.\"Specify the path to the directory containing the Unicode character
.\"tables. The default path is DATADIR/ucdata.
.TP
.B olcWriteTimeout: <integer>
Specify the number of seconds to wait before forcibly closing
a connection with an outstanding write. This allows recovery from
various network hang conditions. A setting of 0 disables this
feature. The default is 0.
.SH TLS OPTIONS
If
.B slapd
......
......@@ -472,7 +472,9 @@ along with this option.
.B idletimeout <integer>
Specify the number of seconds to wait before forcibly closing
an idle client connection. A idletimeout of 0 disables this
feature. The default is 0.
feature. The default is 0. You may also want to set the
.B writetimeout
option.
.TP
.B include <filename>
Read additional configuration information from the given file before
......@@ -985,6 +987,12 @@ The default is 1.
.\".B ucdata-path <path>
.\"Specify the path to the directory containing the Unicode character
.\"tables. The default path is DATADIR/ucdata.
.TP
.B writetimeout <integer>
Specify the number of seconds to wait before forcibly closing
a connection with an outstanding write. This allows recovery from
various network hang conditions. A writetimeout of 0 disables this
feature. The default is 0.
.SH TLS OPTIONS
If
.B slapd
......
......@@ -714,6 +714,9 @@ static ConfigTable config_back_cf_table[] = {
&config_updateref, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' "
"EQUALITY caseIgnoreMatch "
"SUP labeledURI )", NULL, NULL },
{ "writetimeout", "timeout", 2, 2, 0, ARG_INT,
&global_writetimeout, "( OLcfgGlAt:88 NAME 'olcWriteTimeout' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
NULL, NULL, NULL, NULL }
};
......@@ -772,7 +775,7 @@ static ConfigOCs cf_ocs[] = {
"olcTLSCACertificatePath $ olcTLSCertificateFile $ "
"olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
"olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ "
"olcTLSCRLFile $ olcToolThreads $ "
"olcTLSCRLFile $ olcToolThreads $ olcWriteTimeout $ "
"olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
"olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
{ "( OLcfgGlOc:2 "
......
......@@ -62,6 +62,7 @@ slap_mask_t global_allows = 0;
slap_mask_t global_disallows = 0;
int global_gentlehup = 0;
int global_idletimeout = 0;
int global_writetimeout = 0;
char *global_host = NULL;
char *global_realm = NULL;
char *sasl_host = NULL;
......
......@@ -222,17 +222,23 @@ int connections_shutdown(void)
*/
int connections_timeout_idle(time_t now)
{
int i = 0;
int i = 0, writers = 0;
int connindex;
Connection* c;
time_t old;
old = slapd_get_writetime();
for( c = connection_first( &connindex );
c != NULL;
c = connection_next( c, &connindex ) )
{
/* Don't timeout a slow-running request or a persistent
* outbound connection */
if( c->c_n_ops_executing || c->c_conn_state == SLAP_C_CLIENT ) {
* outbound connection. But if it has a writewaiter, see
* if the waiter has been there too long.
*/
if(( c->c_n_ops_executing && !c->c_writewaiter)
|| c->c_conn_state == SLAP_C_CLIENT ) {
continue;
}
......@@ -241,9 +247,21 @@ int connections_timeout_idle(time_t now)
connection_closing( c, "idletimeout" );
connection_close( c );
i++;
continue;
}
if ( c->c_writewaiter ) {
writers = 1;
if( difftime( c->c_activitytime+global_writetimeout, now) < 0 ) {
/* close it */
connection_closing( c, "writetimeout" );
connection_close( c );
i++;
}
}
}
connection_done( c );
if ( !writers )
slapd_clr_writetime( old );
return i;
}
......
......@@ -86,6 +86,8 @@ static ber_socket_t wake_sds[2]
;
static int emfile;
static time_t chk_writetime;
static volatile int waking;
#ifdef NO_THREADS
#define WAKE_LISTENER(w) do { \
......@@ -955,6 +957,9 @@ slapd_set_write( ber_socket_t s, int wake )
SLAP_SOCK_SET_WRITE( s );
slap_daemon.sd_nwriters++;
}
if (( wake & 2 ) && global_writetimeout ) {
chk_writetime = slap_get_time();
}
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
WAKE_LISTENER(wake);
......@@ -988,6 +993,25 @@ slapd_set_read( ber_socket_t s, int wake )
WAKE_LISTENER(wake);
}
time_t
slapd_get_writetime()
{
time_t cur;
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
cur = chk_writetime;
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
return cur;
}
void
slapd_clr_writetime( time_t old )
{
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
if ( chk_writetime == old )
chk_writetime = 0;
ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
}
static void
slapd_close( ber_socket_t s )
{
......@@ -2035,24 +2059,12 @@ slapd_daemon_task(
{
int l;
time_t last_idle_check = 0;
struct timeval idle;
int ebadf = 0;
#define SLAPD_IDLE_CHECK_LIMIT 4
if ( global_idletimeout > 0 ) {
last_idle_check = slap_get_time();
/* Set the select timeout.
* Don't just truncate, preserve the fractions of
* seconds to prevent sleeping for zero time.
*/
idle.tv_sec = global_idletimeout / SLAPD_IDLE_CHECK_LIMIT;
idle.tv_usec = global_idletimeout - \
( idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT );
idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT;
} else {
idle.tv_sec = 0;
idle.tv_usec = 0;
}
slapd_add( wake_sds[0], 0, NULL );
......@@ -2157,14 +2169,34 @@ slapd_daemon_task(
now = slap_get_time();
if ( ( global_idletimeout > 0 ) &&
difftime( last_idle_check +
global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 )
{
connections_timeout_idle( now );
last_idle_check = now;
if ( global_idletimeout > 0 || chk_writetime ) {
int check = 0;
/* Set the select timeout.
* Don't just truncate, preserve the fractions of
* seconds to prevent sleeping for zero time.
*/
if ( chk_writetime ) {
tv.tv_sec = global_writetimeout;
tv.tv_usec = global_writetimeout;
if ( difftime( chk_writetime, now ) < 0 )
check = 2;
} else {
tv.tv_sec = global_idletimeout / SLAPD_IDLE_CHECK_LIMIT;
tv.tv_usec = global_idletimeout - \
( tv.tv_sec * SLAPD_IDLE_CHECK_LIMIT );
tv.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT;
if ( difftime( last_idle_check +
global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 )
check = 1;
}
if ( check ) {
connections_timeout_idle( now );
last_idle_check = now;
}
} else {
tv.tv_sec = 0;
tv.tv_usec = 0;
}
tv = idle;
#ifdef SIGHUP
if ( slapd_gentle_shutdown ) {
......
......@@ -843,6 +843,8 @@ LDAP_SLAPD_F (void) slapd_set_write LDAP_P((ber_socket_t s, int wake));
LDAP_SLAPD_F (void) slapd_clr_write LDAP_P((ber_socket_t s, int wake));
LDAP_SLAPD_F (void) slapd_set_read LDAP_P((ber_socket_t s, int wake));
LDAP_SLAPD_F (int) slapd_clr_read LDAP_P((ber_socket_t s, int wake));
LDAP_SLAPD_F (void) slapd_clr_writetime LDAP_P((time_t old));
LDAP_SLAPD_F (time_t) slapd_get_writetime LDAP_P((void));
LDAP_SLAPD_V (volatile sig_atomic_t) slapd_abrupt_shutdown;
LDAP_SLAPD_V (volatile sig_atomic_t) slapd_shutdown;
......@@ -1933,6 +1935,7 @@ LDAP_SLAPD_V (const char) Versionstr[];
LDAP_SLAPD_V (int) global_gentlehup;
LDAP_SLAPD_V (int) global_idletimeout;
LDAP_SLAPD_V (int) global_writetimeout;
LDAP_SLAPD_V (char *) global_host;
LDAP_SLAPD_V (char *) global_realm;
LDAP_SLAPD_V (char *) sasl_host;
......
......@@ -211,7 +211,7 @@ static long send_ldap_ber(
/* wait for socket to be write-ready */
ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
conn->c_writewaiter = 1;
slapd_set_write( conn->c_sd, 1 );
slapd_set_write( conn->c_sd, 2 );
ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment