]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/connection.c
Plug mutex/rwlock leaks (destroy them)
[openldap] / servers / slapd / connection.c
index 05e8122c62cdcfa6110bb61fe61b0e9f959de708..83bed4e9495f57b246d02dc09a10288c0afe5cba 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2009 The OpenLDAP Foundation.
+ * Copyright 1998-2010 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "lutil.h"
 #include "slap.h"
 
+#ifdef LDAP_CONNECTIONLESS
+#include "../../libraries/liblber/lber-int.h"  /* ber_int_sb_read() */
+#endif
+
 #ifdef LDAP_SLAPI
 #include "slapi/slapi.h"
 #endif
@@ -48,28 +52,10 @@ static ldap_pvt_thread_mutex_t connections_mutex;
 static Connection *connections = NULL;
 
 static ldap_pvt_thread_mutex_t conn_nextid_mutex;
-static unsigned long conn_nextid = 0;
+static unsigned long conn_nextid = SLAPD_SYNC_SYNCCONN_OFFSET;
 
 static const char conn_lost_str[] = "connection lost";
 
-/* structure state (protected by connections_mutex) */
-enum sc_struct_state {
-       SLAP_C_UNINITIALIZED = 0,       /* MUST BE ZERO (0) */
-       SLAP_C_UNUSED,
-       SLAP_C_USED,
-       SLAP_C_PENDING
-};
-
-/* connection state (protected by c_mutex ) */
-enum sc_conn_state {
-       SLAP_C_INVALID = 0,             /* MUST BE ZERO (0) */
-       SLAP_C_INACTIVE,                /* zero threads */
-       SLAP_C_CLOSING,                 /* closing */
-       SLAP_C_ACTIVE,                  /* one or more threads */
-       SLAP_C_BINDING,                 /* binding */
-       SLAP_C_CLIENT                   /* outbound client conn */
-};
-
 const char *
 connection_state2str( int state )
 {
@@ -242,14 +228,15 @@ int connections_timeout_idle(time_t now)
                        continue;
                }
 
-               if( difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
+               if( global_idletimeout && 
+                       difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
                        /* close it */
                        connection_closing( c, "idletimeout" );
                        connection_close( c );
                        i++;
                        continue;
                }
-               if ( c->c_writewaiter ) {
+               if ( c->c_writewaiter && global_writetimeout ) {
                        writers = 1;
                        if( difftime( c->c_activitytime+global_writetimeout, now) < 0 ) {
                                /* close it */
@@ -260,7 +247,7 @@ int connections_timeout_idle(time_t now)
                }
        }
        connection_done( c );
-       if ( !writers )
+       if ( old && !writers )
                slapd_clr_writetime( old );
 
        return i;
@@ -752,11 +739,39 @@ static void connection_abandon( Connection *c )
        }
 }
 
+static void
+connection_wake_writers( Connection *c )
+{
+       /* wake write blocked operations */
+       ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
+       if ( c->c_writers > 0 ) {
+               c->c_writers = -c->c_writers;
+               ldap_pvt_thread_cond_broadcast( &c->c_write1_cv );
+               ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
+               if ( c->c_writewaiter ) {
+                       ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
+                       ldap_pvt_thread_cond_signal( &c->c_write2_cv );
+                       slapd_clr_write( c->c_sd, 1 );
+                       ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
+               }
+               ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
+               while ( c->c_writers ) {
+                       ldap_pvt_thread_cond_wait( &c->c_write1_cv, &c->c_write1_mutex );
+               }
+               ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
+       } else {
+               ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
+               slapd_clr_write( c->c_sd, 1 );
+       }
+}
+
 void connection_closing( Connection *c, const char *why )
 {
        assert( connections != NULL );
        assert( c != NULL );
-       assert( c->c_struct_state == SLAP_C_USED );
+
+       if ( c->c_struct_state != SLAP_C_USED ) return;
+
        assert( c->c_conn_state != SLAP_C_INVALID );
 
        /* c_mutex must be locked by caller */
@@ -776,26 +791,7 @@ void connection_closing( Connection *c, const char *why )
                connection_abandon( c );
 
                /* wake write blocked operations */
-               ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
-               if ( c->c_writers > 0 ) {
-                       c->c_writers = -c->c_writers;
-                       ldap_pvt_thread_cond_broadcast( &c->c_write1_cv );
-                       ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
-                       if ( c->c_writewaiter ) {
-                               ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
-                               ldap_pvt_thread_cond_signal( &c->c_write2_cv );
-                               slapd_clr_write( c->c_sd, 1 );
-                               ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
-                       }
-                       ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
-                       while ( c->c_writers ) {
-                               ldap_pvt_thread_cond_wait( &c->c_write1_cv, &c->c_write1_mutex );
-                       }
-                       ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
-               } else {
-                       ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
-                       slapd_clr_write( c->c_sd, 1 );
-               }
+               connection_wake_writers( c );
 
        } else if( why == NULL && c->c_close_reason == conn_lost_str ) {
                /* Client closed connection after doing Unbind. */
@@ -808,7 +804,9 @@ connection_close( Connection *c )
 {
        assert( connections != NULL );
        assert( c != NULL );
-       assert( c->c_struct_state == SLAP_C_USED );
+
+       if ( c->c_struct_state != SLAP_C_USED ) return;
+
        assert( c->c_conn_state == SLAP_C_CLOSING );
 
        /* NOTE: c_mutex should be locked by caller */
@@ -1269,6 +1267,11 @@ int connection_read_activate( ber_socket_t s )
        if ( rc )
                return rc;
 
+       /* Don't let blocked writers block a pause request */
+       if ( connections[s].c_writewaiter &&
+               ldap_pvt_thread_pool_pausing( &connection_pool ))
+               connection_wake_writers( &connections[s] );
+
        rc = ldap_pvt_thread_pool_submit( &connection_pool,
                connection_read_thread, (void *)(long)s );
 
@@ -1363,6 +1366,11 @@ connection_read( ber_socket_t s, conn_readinfo *cri )
                            c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 );
                        slap_sasl_external( c, c->c_tls_ssf, &authid );
                        if ( authid.bv_val ) free( authid.bv_val );
+               } else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
+                       LBER_SB_OPT_NEEDS_WRITE, NULL )) {      /* need to retry */
+                       slapd_set_write( s, 1 );
+                       connection_return( c );
+                       return 0;
                }
 
                /* if success and data is ready, fall thru to data input loop */
@@ -1862,6 +1870,14 @@ int connection_write(ber_socket_t s)
                return -1;
        }
 
+#ifdef HAVE_TLS
+       if ( c->c_is_tls && c->c_needs_tls_accept ) {
+               connection_return( c );
+               connection_read_activate( s );
+               return 0;
+       }
+#endif
+
        c->c_n_write++;
 
        Debug( LDAP_DEBUG_TRACE,