Commit f2cc7e8a authored by Howard Chu's avatar Howard Chu
Browse files

ITS#5836, add writetimeout keyword for timing out hung writers

parent a77e7a47
......@@ -706,6 +706,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 }
};
......@@ -764,7 +767,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;
......
......@@ -218,9 +218,12 @@ 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;
......@@ -240,9 +243,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 { \
......@@ -954,6 +956,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);
......@@ -987,6 +992,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 )
{
......@@ -2033,24 +2057,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 );
......@@ -2155,14 +2167,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 ) {
......
......@@ -842,6 +842,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;
......@@ -1930,6 +1932,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;
......
......@@ -210,7 +210,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 );
......
Markdown is supported
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