Commit 4d7be1c1 authored by Howard Chu's avatar Howard Chu
Browse files

ITS#9112 cleaner error handling during connection setup

And additional debug code for tracking errant close()s
parent 230b4696
......@@ -522,6 +522,23 @@ Connection * connection_init(
Debug( LDAP_DEBUG_ANY,
"connection_init(%d, %s): set nonblocking failed\n",
s, c->c_peer_name.bv_val );
c->c_listener = NULL;
if(c->c_peer_domain.bv_val != NULL) {
free(c->c_peer_domain.bv_val);
}
BER_BVZERO( &c->c_peer_domain );
if(c->c_peer_name.bv_val != NULL) {
free(c->c_peer_name.bv_val);
}
BER_BVZERO( &c->c_peer_name );
ber_sockbuf_free( c->c_sb );
c->c_sb = NULL;
c->c_sd = AC_SOCKET_INVALID;
ldap_pvt_thread_mutex_unlock( &c->c_mutex );
return NULL;
}
ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
......
......@@ -1085,6 +1085,50 @@ slapd_sock2fd( ber_socket_t s )
}
#endif
#ifdef DEBUG_CLOSE
/* Was used to find a bug causing slapd's descriptors to be closed
* out from under it. Tracked it down to a long-standing (from 2009)
* bug in Heimdal https://github.com/heimdal/heimdal/issues/431 .
* Leaving this here for future use, if necessary.
*/
#include <dlfcn.h>
#ifndef RTLD_NEXT
#define RTLD_NEXT (void *)-1L
#endif
static char *newconns;
typedef int (closefunc)(int fd);
static closefunc *close_ptr;
int close( int s )
{
if (newconns) {
Debug( LDAP_DEBUG_CONNS,
"daemon: close(%ld)\n", s, 0, 0 );
if (s >= 0 && s < dtblsize && newconns[s])
assert(newconns[s] == 2);
}
return close_ptr ? close_ptr(s) : -1;
}
void slapd_debug_close()
{
if (dtblsize)
newconns = ch_calloc(1, dtblsize);
close_ptr = dlsym(RTLD_NEXT, "close");
}
void slapd_set_close(int fd)
{
newconns[fd] = 3;
}
#define SETUP_CLOSE() slapd_debug_close()
#define SET_CLOSE(fd) slapd_set_close(fd)
#define CLR_CLOSE(fd) if (newconns[fd]) newconns[fd]--
#else
#define SETUP_CLOSE(fd)
#define SET_CLOSE(fd)
#define CLR_CLOSE(fd)
#endif
/*
* Add a descriptor to daemon control
*
......@@ -1148,6 +1192,7 @@ slapd_remove(
if ( waswriter ) slap_daemon[id].sd_nwriters--;
SLAP_SOCK_DEL(id, s);
CLR_CLOSE(s);
if ( sb )
ber_sockbuf_free(sb);
......@@ -1253,6 +1298,7 @@ slapd_close( ber_socket_t s )
{
Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
(long) s );
CLR_CLOSE( SLAP_FD2SOCK(s) );
tcp_close( SLAP_FD2SOCK(s) );
#ifdef HAVE_WINSOCK
slapd_sockdel( s );
......@@ -1862,6 +1908,8 @@ slapd_daemon_init( const char *urls )
dtblsize = FD_SETSIZE;
#endif /* ! HAVE_SYSCONF && ! HAVE_GETDTABLESIZE */
SETUP_CLOSE();
/* open a pipe (or something equivalent connected to itself).
* we write a byte on this fd whenever we catch a signal. The main
* loop will be select'ing on this socket, and will wake up when
......@@ -2070,6 +2118,11 @@ slap_listener(
# endif /* LDAP_PF_LOCAL */
s = accept( SLAP_FD2SOCK( sl->sl_sd ), (struct sockaddr *) &from, &len );
if ( s != AC_SOCKET_INVALID ) {
SET_CLOSE(s);
}
Debug( LDAP_DEBUG_CONNS,
"daemon: accept() = %ld\n", s, 0, 0 );
/* Resume the listener FD to allow concurrent-processing of
* additional incoming connections.
......@@ -2141,6 +2194,8 @@ slap_listener(
Debug( LDAP_DEBUG_ANY,
"slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
"errno=%d (%s)\n", (long) sfd, err, sock_errstr(err) );
slapd_close(sfd);
return 0;
}
#endif /* SO_KEEPALIVE */
#ifdef TCP_NODELAY
......@@ -2153,6 +2208,8 @@ slap_listener(
Debug( LDAP_DEBUG_ANY,
"slapd(%ld): setsockopt(TCP_NODELAY) failed "
"errno=%d (%s)\n", (long) sfd, err, sock_errstr(err) );
slapd_close(sfd);
return 0;
}
#endif /* TCP_NODELAY */
}
......@@ -3322,6 +3379,9 @@ slap_unpause_server( void )
void
slapd_add_internal( ber_socket_t s, int isactive )
{
if (!isactive) {
SET_CLOSE(s);
}
slapd_add( s, isactive, NULL, -1 );
}
......
......@@ -401,11 +401,16 @@ int main( int argc, char **argv )
slap_sl_mem_init();
(void) ldap_pvt_thread_initialize();
serverName = lutil_progname( "slapd", argc, argv );
if ( strcmp( serverName, "slapd" ) ) {
#ifdef DEBUG_CLOSE
extern void slapd_debug_close();
slapd_debug_close();
#endif
for (i=0; tools[i].name; i++) {
if ( !strcmp( serverName, tools[i].name ) ) {
rc = tools[i].func(argc, argv);
......@@ -649,6 +654,10 @@ int main( int argc, char **argv )
optarg );
}
#ifdef DEBUG_CLOSE
extern void slapd_debug_close();
slapd_debug_close();
#endif
/* try full option string first */
for ( i = 0; tools[i].name; i++ ) {
if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) {
......
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