diff --git a/doc/man/man5/lloadd.conf.5 b/doc/man/man5/lloadd.conf.5 index b6031972a2..bae0fef4e9 100644 --- a/doc/man/man5/lloadd.conf.5 +++ b/doc/man/man5/lloadd.conf.5 @@ -290,6 +290,12 @@ process PDUs from the connection until there is no more data to be read or this limit is reached when the I/O thread can pick it up again. Very high values have a potential to cause some connections to be starved in a very high-bandwidth environment. The default is 1000. +.TP +.B iotimeout +Specify the number of milliseconds to wait before forcibly closing +a connection with an outstanding write. This allows faster recovery from +various network hang conditions. An iotimeout of 0 disables this feature. +The default is 10000. .SH TLS OPTIONS If diff --git a/servers/lloadd/backend.c b/servers/lloadd/backend.c index 4277021dd1..d31e4b2ec8 100644 --- a/servers/lloadd/backend.c +++ b/servers/lloadd/backend.c @@ -117,8 +117,6 @@ upstream_name_cb( int result, struct evutil_addrinfo *res, void *arg ) } /* Asynchronous connect */ if ( rc ) { - struct timeval tv = { slap_write_timeout / 1000, - 1000 * ( slap_write_timeout % 1000 ) }; PendingConnection *conn; if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) { @@ -145,7 +143,7 @@ upstream_name_cb( int result, struct evutil_addrinfo *res, void *arg ) goto fail; } - event_add( conn->event, &tv ); + event_add( conn->event, lload_write_timeout ); LDAP_LIST_INSERT_HEAD( &b->b_connecting, conn, next ); Debug( LDAP_DEBUG_CONNS, "upstream_name_cb: " "connection to backend uri=%s in progress\n", @@ -353,8 +351,6 @@ backend_connect( evutil_socket_t s, short what, void *arg ) s, (struct sockaddr *)&addr, sizeof(struct sockaddr_un) ); /* Asynchronous connect */ if ( rc ) { - struct timeval tv = { slap_write_timeout / 1000, - 1000 * ( slap_write_timeout % 1000 ) }; PendingConnection *conn; if ( errno != EINPROGRESS && errno != EWOULDBLOCK ) { @@ -378,7 +374,7 @@ backend_connect( evutil_socket_t s, short what, void *arg ) goto fail; } - event_add( conn->event, &tv ); + event_add( conn->event, lload_write_timeout ); LDAP_LIST_INSERT_HEAD( &b->b_connecting, conn, next ); Debug( LDAP_DEBUG_CONNS, "backend_connect: " "connection to backend uri=%s in progress\n", diff --git a/servers/lloadd/config.c b/servers/lloadd/config.c index aa8b1a06e6..1417368c35 100644 --- a/servers/lloadd/config.c +++ b/servers/lloadd/config.c @@ -69,6 +69,8 @@ char *global_host = NULL; static FILE *logfile; static char *logfileName; +static struct timeval timeout_write_tv = { 10, 0 }; + lload_features_t lload_features; ber_len_t sockbuf_max_incoming_client = LLOAD_SB_MAX_INCOMING_CLIENT; @@ -76,7 +78,7 @@ ber_len_t sockbuf_max_incoming_upstream = LLOAD_SB_MAX_INCOMING_UPSTREAM; int slap_conn_max_pdus_per_cycle = LLOAD_CONN_MAX_PDUS_PER_CYCLE_DEFAULT; -int slap_write_timeout = 10000; +struct timeval *lload_write_timeout = &timeout_write_tv; char *slapd_pid_file = NULL; char *slapd_args_file = NULL; @@ -148,6 +150,7 @@ enum { CFG_TLS_CERT, CFG_TLS_KEY, CFG_RESCOUNT, + CFG_IOTIMEOUT, CFG_LAST }; @@ -381,6 +384,10 @@ static ConfigTable config_back_cf_table[] = { NULL, #endif }, + { "iotimeout", "ms timeout", 2, 2, 0, + ARG_INT|ARG_MAGIC|CFG_IOTIMEOUT, + &config_generic, + }, { NULL, NULL, 0, 0, 0, ARG_IGNORED, NULL } }; @@ -457,6 +464,21 @@ config_generic( ConfigArgs *c ) slap_conn_max_pdus_per_cycle = c->value_int; break; + case CFG_IOTIMEOUT: + if ( c->value_int < 0 ) { + snprintf( c->cr_msg, sizeof(c->cr_msg), + "iotimeout=%d invalid", c->value_int ); + Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); + return 1; + } else if ( c->value_int > 0 ) { + timeout_write_tv.tv_sec = c->value_int / 1000; + timeout_write_tv.tv_sec = 1000 * ( c->value_int % 1000 ); + lload_write_timeout = &timeout_write_tv; + } else { + lload_write_timeout = NULL; + } + break; + default: Debug( LDAP_DEBUG_ANY, "%s: unknown CFG_TYPE %d\n", c->log, c->type ); diff --git a/servers/lloadd/connection.c b/servers/lloadd/connection.c index c0e458148b..907bbe2aa5 100644 --- a/servers/lloadd/connection.c +++ b/servers/lloadd/connection.c @@ -269,7 +269,7 @@ connection_write_cb( evutil_socket_t s, short what, void *arg ) CONNECTION_LOCK_DESTROY(c); return; } - event_add( c->c_write_event, NULL ); + event_add( c->c_write_event, lload_write_timeout ); } else { c->c_pendingber = NULL; } diff --git a/servers/lloadd/proto-slap.h b/servers/lloadd/proto-slap.h index 5df2ce922b..45eb2c1da2 100644 --- a/servers/lloadd/proto-slap.h +++ b/servers/lloadd/proto-slap.h @@ -242,8 +242,6 @@ LDAP_SLAPD_V (ber_len_t) sockbuf_max_incoming_client; LDAP_SLAPD_V (ber_len_t) sockbuf_max_incoming_upstream; LDAP_SLAPD_V (int) slap_conn_max_pdus_per_cycle; -LDAP_SLAPD_V (int) slap_write_timeout; - LDAP_SLAPD_V (lload_features_t) lload_features; LDAP_SLAPD_V (slap_mask_t) global_allows; @@ -253,6 +251,9 @@ LDAP_SLAPD_V (const char) Versionstr[]; LDAP_SLAPD_V (int) global_gentlehup; LDAP_SLAPD_V (int) global_idletimeout; + +LDAP_SLAPD_V (struct timeval *) lload_write_timeout; + LDAP_SLAPD_V (char *) global_host; LDAP_SLAPD_V (int) lber_debug; LDAP_SLAPD_V (int) ldap_syslog;