]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/daemon.c
Plug mutex/rwlock leaks (destroy them)
[openldap] / servers / slapd / daemon.c
index 23193d149846e0efe5b42c7b78ccecaf57010f47..a504842ae0266acaac5593d44bbe82429ed7b007 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.
  * Portions Copyright 2007 by Howard Chu, Symas Corporation.
  * All rights reserved.
  *
@@ -73,6 +73,11 @@ ber_socket_t dtblsize;
 slap_ssf_t local_ssf = LDAP_PVT_SASL_LOCAL_SSF;
 struct runqueue_s slapd_rq;
 
+#ifdef LDAP_TCP_BUFFER
+int slapd_tcp_rmem;
+int slapd_tcp_wmem;
+#endif /* LDAP_TCP_BUFFER */
+
 Listener **slap_listeners = NULL;
 
 #ifndef SLAPD_LISTEN_BACKLOG
@@ -687,16 +692,16 @@ slapd_slp_init( const char* urls )
        for ( i = 0; slapd_srvurls[i] != NULL; i++ ) {
                if ( strcmp( slapd_srvurls[i], "ldap:///" ) == 0 ) {
                        slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
-                               strlen( global_host ) +
+                               global_host_bv.bv_len +
                                sizeof( LDAP_SRVTYPE_PREFIX ) );
                        strcpy( lutil_strcopy(slapd_srvurls[i],
-                               LDAP_SRVTYPE_PREFIX ), global_host );
+                               LDAP_SRVTYPE_PREFIX ), global_host_bv.bv_val );
                } else if ( strcmp( slapd_srvurls[i], "ldaps:///" ) == 0 ) {
                        slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
-                               strlen( global_host ) +
+                               global_host_bv.bv_len +
                                sizeof( LDAPS_SRVTYPE_PREFIX ) );
                        strcpy( lutil_strcopy(slapd_srvurls[i],
-                               LDAPS_SRVTYPE_PREFIX ), global_host );
+                               LDAPS_SRVTYPE_PREFIX ), global_host_bv.bv_val );
                }
        }
 
@@ -957,7 +962,7 @@ slapd_set_write( ber_socket_t s, int wake )
                SLAP_SOCK_SET_WRITE( s );
                slap_daemon.sd_nwriters++;
        }
-       if (( wake & 2 ) && global_writetimeout ) {
+       if (( wake & 2 ) && global_writetimeout && !chk_writetime ) {
                chk_writetime = slap_get_time();
        }
 
@@ -984,13 +989,17 @@ slapd_clr_read( ber_socket_t s, int wake )
 void
 slapd_set_read( ber_socket_t s, int wake )
 {
+       int do_wake = 1;
        ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
 
-       assert( SLAP_SOCK_IS_ACTIVE( s ));
-       if (!SLAP_SOCK_IS_READ( s )) SLAP_SOCK_SET_READ( s );
-
+       if( SLAP_SOCK_IS_ACTIVE( s ) && !SLAP_SOCK_IS_READ( s )) {
+               SLAP_SOCK_SET_READ( s );
+       } else {
+               do_wake = 0;
+       }
        ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
-       WAKE_LISTENER(wake);
+       if ( do_wake )
+               WAKE_LISTENER(wake);
 }
 
 time_t
@@ -1315,6 +1324,11 @@ slap_open_listener(
        }
 #endif /* HAVE_TLS */
 
+#ifdef LDAP_TCP_BUFFER
+       l.sl_tcp_rmem = 0;
+       l.sl_tcp_wmem = 0;
+#endif /* LDAP_TCP_BUFFER */
+
        port = (unsigned short) lud->lud_port;
 
        tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme);
@@ -1478,7 +1492,7 @@ slap_open_listener(
                 * create/unlink the socket; likely need exec perms to access
                 * the socket (ITS#4709) */
                {
-                       mode_t old_umask;
+                       mode_t old_umask = 0;
 
                        if ( (*sal)->sa_family == AF_LOCAL ) {
                                old_umask = umask( 0 );
@@ -1486,7 +1500,7 @@ slap_open_listener(
 #endif /* LDAP_PF_LOCAL */
                        rc = bind( s, *sal, addrlen );
 #ifdef LDAP_PF_LOCAL
-                       if ( (*sal)->sa_family == AF_LOCAL ) {
+                       if ( old_umask != 0 ) {
                                umask( old_umask );
                        }
                }
@@ -1610,6 +1624,7 @@ slapd_daemon_init( const char *urls )
                        "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
                return rc;
        }
+       ber_pvt_socket_set_nonblock( wake_sds[1], 1 );
 
        SLAP_SOCK_INIT;
 
@@ -1705,9 +1720,12 @@ close_listeners(
 
        for ( l = 0; slap_listeners[l] != NULL; l++ ) {
                Listener *lr = slap_listeners[l];
+               slap_listeners[l] = NULL;
 
                if ( lr->sl_sd != AC_SOCKET_INVALID ) {
-                       if ( remove ) slapd_remove( lr->sl_sd, NULL, 0, 0, 0 );
+                       int s = lr->sl_sd;
+                       lr->sl_sd = AC_SOCKET_INVALID;
+                       if ( remove ) slapd_remove( s, NULL, 0, 0, 0 );
 
 #ifdef LDAP_PF_LOCAL
                        if ( lr->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
@@ -1715,7 +1733,7 @@ close_listeners(
                        }
 #endif /* LDAP_PF_LOCAL */
 
-                       slapd_close( lr->sl_sd );
+                       slapd_close( s );
                }
 
                if ( lr->sl_url.bv_val ) {
@@ -1727,7 +1745,6 @@ close_listeners(
                }
 
                free( lr );
-               slap_listeners[l] = NULL;
        }
 }
 
@@ -2081,6 +2098,131 @@ slapd_daemon_task(
                        continue;
 #endif /* LDAP_CONNECTIONLESS */
 
+               /* FIXME: TCP-only! */
+#ifdef LDAP_TCP_BUFFER
+               if ( 1 ) {
+                       int origsize, size, realsize, rc;
+                       socklen_t optlen;
+                       char buf[ SLAP_TEXT_BUFLEN ];
+
+                       size = 0;
+                       if ( slap_listeners[l]->sl_tcp_rmem > 0 ) {
+                               size = slap_listeners[l]->sl_tcp_rmem;
+                       } else if ( slapd_tcp_rmem > 0 ) {
+                               size = slapd_tcp_rmem;
+                       }
+
+                       if ( size > 0 ) {
+                               optlen = sizeof( origsize );
+                               rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+                                       SOL_SOCKET,
+                                       SO_RCVBUF,
+                                       (void *)&origsize,
+                                       &optlen );
+
+                               if ( rc ) {
+                                       int err = sock_errno();
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "slapd_daemon_task: getsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
+                                               err, sock_errstr(err), 0 );
+                               }
+
+                               optlen = sizeof( size );
+                               rc = setsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+                                       SOL_SOCKET,
+                                       SO_RCVBUF,
+                                       (const void *)&size,
+                                       optlen );
+
+                               if ( rc ) {
+                                       int err = sock_errno();
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "slapd_daemon_task: setsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
+                                               err, sock_errstr(err), 0 );
+                               }
+
+                               optlen = sizeof( realsize );
+                               rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+                                       SOL_SOCKET,
+                                       SO_RCVBUF,
+                                       (void *)&realsize,
+                                       &optlen );
+
+                               if ( rc ) {
+                                       int err = sock_errno();
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "slapd_daemon_task: getsockopt(SO_RCVBUF) failed errno=%d (%s)\n",
+                                               err, sock_errstr(err), 0 );
+                               }
+
+                               snprintf( buf, sizeof( buf ),
+                                       "url=%s (#%d) RCVBUF original size=%d requested size=%d real size=%d", 
+                                       slap_listeners[l]->sl_url.bv_val, l, origsize, size, realsize );
+                               Debug( LDAP_DEBUG_ANY,
+                                       "slapd_daemon_task: %s\n",
+                                       buf, 0, 0 );
+                       }
+
+                       size = 0;
+                       if ( slap_listeners[l]->sl_tcp_wmem > 0 ) {
+                               size = slap_listeners[l]->sl_tcp_wmem;
+                       } else if ( slapd_tcp_wmem > 0 ) {
+                               size = slapd_tcp_wmem;
+                       }
+
+                       if ( size > 0 ) {
+                               optlen = sizeof( origsize );
+                               rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+                                       SOL_SOCKET,
+                                       SO_SNDBUF,
+                                       (void *)&origsize,
+                                       &optlen );
+
+                               if ( rc ) {
+                                       int err = sock_errno();
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "slapd_daemon_task: getsockopt(SO_SNDBUF) failed errno=%d (%s)\n",
+                                               err, sock_errstr(err), 0 );
+                               }
+
+                               optlen = sizeof( size );
+                               rc = setsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+                                       SOL_SOCKET,
+                                       SO_SNDBUF,
+                                       (const void *)&size,
+                                       optlen );
+
+                               if ( rc ) {
+                                       int err = sock_errno();
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "slapd_daemon_task: setsockopt(SO_SNDBUF) failed errno=%d (%s)",
+                                               err, sock_errstr(err), 0 );
+                               }
+
+                               optlen = sizeof( realsize );
+                               rc = getsockopt( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ),
+                                       SOL_SOCKET,
+                                       SO_SNDBUF,
+                                       (void *)&realsize,
+                                       &optlen );
+
+                               if ( rc ) {
+                                       int err = sock_errno();
+                                       Debug( LDAP_DEBUG_ANY,
+                                               "slapd_daemon_task: getsockopt(SO_SNDBUF) failed errno=%d (%s)\n",
+                                               err, sock_errstr(err), 0 );
+                               }
+
+                               snprintf( buf, sizeof( buf ),
+                                       "url=%s (#%d) SNDBUF original size=%d requested size=%d real size=%d", 
+                                       slap_listeners[l]->sl_url.bv_val, l, origsize, size, realsize );
+                               Debug( LDAP_DEBUG_ANY,
+                                       "slapd_daemon_task: %s\n",
+                                       buf, 0, 0 );
+                       }
+               }
+#endif /* LDAP_TCP_BUFFER */
+
                if ( listen( SLAP_FD2SOCK( slap_listeners[l]->sl_sd ), SLAPD_LISTEN_BACKLOG ) == -1 ) {
                        int err = sock_errno();
 
@@ -2177,7 +2319,7 @@ slapd_daemon_task(
                         */
                        if ( chk_writetime ) {
                                tv.tv_sec = global_writetimeout;
-                               tv.tv_usec = global_writetimeout;
+                               tv.tv_usec = 0;
                                if ( difftime( chk_writetime, now ) < 0 )
                                        check = 2;
                        } else {
@@ -2245,7 +2387,7 @@ slapd_daemon_task(
 
                nfds = SLAP_EVENT_MAX;
 
-               if ( global_idletimeout && slap_daemon.sd_nactives ) at = 1;
+               if (( chk_writetime || global_idletimeout ) && slap_daemon.sd_nactives ) at = 1;
 
                ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
 
@@ -2529,7 +2671,7 @@ slapd_daemon_task(
 #endif /* LDAP_DEBUG */
 
                for ( i = 0; i < ns; i++ ) {
-                       int rc = 1, fd, w = 0;
+                       int rc = 1, fd, w = 0, r = 0;
 
                        if ( SLAP_EVENT_IS_LISTENER( i ) ) {
                                rc = slap_listener_activate( SLAP_EVENT_LISTENER( i ) );
@@ -2569,24 +2711,25 @@ slapd_daemon_task(
                                        }
                                }
                                /* If event is a read */
-                               if ( SLAP_EVENT_IS_READ( i ) ) {
+                               if ( SLAP_EVENT_IS_READ( i ))
+                                       r = 1;
+                               if ( r || !w ) {
                                        Debug( LDAP_DEBUG_CONNS,
                                                "daemon: read active on %d\n",
                                                fd, 0, 0 );
 
-                                       SLAP_EVENT_CLR_READ( i );
-                                       connection_read_activate( fd );
-                               } else if ( !w ) {
-                                       Debug( LDAP_DEBUG_CONNS,
-                                               "daemon: hangup on %d\n", fd, 0, 0 );
-                                       if ( SLAP_SOCK_IS_ACTIVE( fd )) {
+                                       if ( r ) {
+                                               SLAP_EVENT_CLR_READ( i );
+                                       } else {
 #ifdef HAVE_EPOLL
                                                /* Don't keep reporting the hangup
                                                 */
-                                               SLAP_EPOLL_SOCK_SET( fd, EPOLLET );
+                                               if ( SLAP_SOCK_IS_ACTIVE( fd )) {
+                                                       SLAP_EPOLL_SOCK_SET( fd, EPOLLET );
+                                               }
 #endif
-                                               connection_hangup( fd );
                                        }
+                                       connection_read_activate( fd );
                                }
                        }
                }
@@ -2661,7 +2804,7 @@ connectionless_init( void )
                if ( !c ) {
                        Debug( LDAP_DEBUG_TRACE,
                                "connectionless_init: failed on %s (%d)\n",
-                               lr->sl_url, lr->sl_sd, 0 );
+                               lr->sl_url.bv_val, lr->sl_sd, 0 );
                        return -1;
                }
                lr->sl_is_udp++;