You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-dev@logging.apache.org by ca...@apache.org on 2008/03/28 10:52:49 UTC

svn commit: r642173 - in /logging/log4cxx/trunk/src: changes/ main/cpp/ main/include/log4cxx/helpers/ test/cpp/net/

Author: carnold
Date: Fri Mar 28 02:52:44 2008
New Revision: 642173

URL: http://svn.apache.org/viewvc?rev=642173&view=rev
Log:
LOGCXX-257: ServerSocket::accept hangs on Unix

Removed:
    logging/log4cxx/trunk/src/main/cpp/socketimpl.cpp
    logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socketimpl.h
Modified:
    logging/log4cxx/trunk/src/changes/changes.xml
    logging/log4cxx/trunk/src/main/cpp/Makefile.am
    logging/log4cxx/trunk/src/main/cpp/datagramsocket.cpp
    logging/log4cxx/trunk/src/main/cpp/exception.cpp
    logging/log4cxx/trunk/src/main/cpp/serversocket.cpp
    logging/log4cxx/trunk/src/main/cpp/socket.cpp
    logging/log4cxx/trunk/src/main/cpp/sockethubappender.cpp
    logging/log4cxx/trunk/src/main/cpp/socketoutputstream.cpp
    logging/log4cxx/trunk/src/main/cpp/syslogwriter.cpp
    logging/log4cxx/trunk/src/main/cpp/telnetappender.cpp
    logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h
    logging/log4cxx/trunk/src/main/include/log4cxx/helpers/serversocket.h
    logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socket.h
    logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socketoutputstream.h
    logging/log4cxx/trunk/src/test/cpp/net/sockethubappendertestcase.cpp
    logging/log4cxx/trunk/src/test/cpp/net/telnetappendertestcase.cpp

Modified: logging/log4cxx/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/changes/changes.xml?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/changes/changes.xml (original)
+++ logging/log4cxx/trunk/src/changes/changes.xml Fri Mar 28 02:52:44 2008
@@ -224,6 +224,7 @@
 <action issue="LOGCXX-253">Transcoder compilation error with utf-8 charset</action>
 <action issue="LOGCXX-254">Add build option for static C RTL</action>
 <action issue="LOGCXX-256">SocketHubAppender fails after accepting connection</action>
+<action issue="LOGCXX-257">ServerSocket::accept hangs on Unix</action>
 </release>
 <release version="0.9.7" date="2004-05-10">
 <action type="fix">Fixed examples source code in the "Short introduction to log4cxx".</action>

Modified: logging/log4cxx/trunk/src/main/cpp/Makefile.am
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/Makefile.am?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/Makefile.am (original)
+++ logging/log4cxx/trunk/src/main/cpp/Makefile.am Fri Mar 28 02:52:44 2008
@@ -139,7 +139,6 @@
         socketappender.cpp \
         socketappenderskeleton.cpp \
         sockethubappender.cpp \
-        socketimpl.cpp \
         socketoutputstream.cpp \
         strftimedateformat.cpp \
         stringhelper.cpp \

Modified: logging/log4cxx/trunk/src/main/cpp/datagramsocket.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/datagramsocket.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/datagramsocket.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/datagramsocket.cpp Fri Mar 28 02:52:44 2008
@@ -19,7 +19,6 @@
 #include <log4cxx/helpers/datagrampacket.h>
 #include <log4cxx/helpers/loglog.h>
 #include <log4cxx/helpers/transcoder.h>
-#include <log4cxx/helpers/socketimpl.h>
 
 #include "apr_network_io.h"
 #include "apr_lib.h"
@@ -121,7 +120,7 @@
    // connect the socket
    status = apr_socket_connect(socket, client_addr);
    if (status != APR_SUCCESS) {
-     throw ConnectException();
+     throw ConnectException(status);
    }
 }
 

Modified: logging/log4cxx/trunk/src/main/cpp/exception.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/exception.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/exception.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/exception.cpp Fri Mar 28 02:52:44 2008
@@ -349,3 +349,79 @@
       Exception::operator=(src);
       return *this;
 }
+
+SocketException::SocketException(const LogString& msg) : IOException(msg) {
+}
+
+SocketException::SocketException(log4cxx_status_t status) : IOException(status) { 
+}
+
+SocketException::SocketException(const SocketException& src)
+     : IOException(src) {
+}
+
+SocketException& SocketException::operator=(const SocketException& src) {
+      IOException::operator=(src);
+      return *this;
+}
+
+ConnectException::ConnectException(log4cxx_status_t status) : SocketException(status) { 
+}
+
+ConnectException::ConnectException(const ConnectException& src)
+     : SocketException(src) {
+}
+
+ConnectException& ConnectException::operator=(const ConnectException& src) {
+      SocketException::operator=(src);
+      return *this;
+}
+
+ClosedChannelException::ClosedChannelException() : SocketException(LOG4CXX_STR("Attempt to write to closed socket")) { 
+}
+
+ClosedChannelException::ClosedChannelException(const ClosedChannelException& src)
+     : SocketException(src) {
+}
+
+ClosedChannelException& ClosedChannelException::operator=(const ClosedChannelException& src) {
+      SocketException::operator=(src);
+      return *this;
+}
+
+BindException::BindException(log4cxx_status_t status) : SocketException(status) { 
+}
+
+BindException::BindException(const BindException& src)
+     : SocketException(src) {
+}
+
+BindException& BindException::operator=(const BindException& src) {
+      SocketException::operator=(src);
+      return *this;
+}
+
+InterruptedIOException::InterruptedIOException(const LogString& msg) : IOException(msg) { 
+}
+
+InterruptedIOException::InterruptedIOException(const InterruptedIOException& src)
+     : IOException(src) {
+}
+
+InterruptedIOException& InterruptedIOException::operator=(const InterruptedIOException& src) {
+      IOException::operator=(src);
+      return *this;
+}
+
+SocketTimeoutException::SocketTimeoutException() 
+    : InterruptedIOException(LOG4CXX_STR("SocketTimeoutException")) { 
+}
+
+SocketTimeoutException::SocketTimeoutException(const SocketTimeoutException& src)
+     : InterruptedIOException(src) {
+}
+
+SocketTimeoutException& SocketTimeoutException::operator=(const SocketTimeoutException& src) {
+      InterruptedIOException::operator=(src);
+      return *this;
+}

Modified: logging/log4cxx/trunk/src/main/cpp/serversocket.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/serversocket.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/serversocket.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/serversocket.cpp Fri Mar 28 02:52:44 2008
@@ -14,75 +14,127 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <log4cxx/logstring.h>
+ 
 #include <log4cxx/helpers/serversocket.h>
-#include <log4cxx/helpers/socket.h>
-
-#include <assert.h>
+#include <log4cxx/helpers/synchronized.h>
+#include "apr_network_io.h"
+#include "apr_pools.h"
+#include "apr_poll.h"
 
 using namespace log4cxx::helpers;
 
 /**  Creates a server socket on a specified port.
 */
-ServerSocket::ServerSocket(int port)
+ServerSocket::ServerSocket(int port) : pool(), mutex(pool), socket(0), timeout(0)
 {
-   InetAddressPtr bindAddr = InetAddress::anyAddress();
-
-   socketImpl = new SocketImpl();
-   socketImpl->create(true);
-   socketImpl->bind(bindAddr, port);
-   socketImpl->listen(50);
+  apr_status_t status =
+    apr_socket_create(&socket, APR_INET, SOCK_STREAM, 
+                      APR_PROTO_TCP, pool.getAPRPool());
+  if (status != APR_SUCCESS) {
+    throw SocketException(status);
+  }
+  
+  status = apr_socket_opt_set(socket, APR_SO_NONBLOCK, 1);
+  if (status != APR_SUCCESS) {
+    throw SocketException(status);
+  }
+  
+        // Create server socket address (including port number)
+  apr_sockaddr_t *server_addr;
+  status =
+      apr_sockaddr_info_get(&server_addr, NULL, APR_INET,
+                                  port, 0, pool.getAPRPool());
+  if (status != APR_SUCCESS) {
+      throw ConnectException(status);
+  }
+
+  // bind the socket to the address
+  status = apr_socket_bind(socket, server_addr);
+  if (status != APR_SUCCESS) {
+      throw BindException(status);
+  }
+  
+  
+  status = apr_socket_listen(socket, 50);
+  if (status != APR_SUCCESS) {
+    throw SocketException(status);
+  }
 }
 
-/** Creates a server socket and binds it to the specified local
-port number, with the specified backlog.
-*/
-ServerSocket::ServerSocket(int port, int backlog)
-{
-   InetAddressPtr bindAddr = InetAddress::anyAddress();
-
-   socketImpl = new SocketImpl();
-   socketImpl->create(true);
-   socketImpl->bind(bindAddr, port);
-   socketImpl->listen(backlog);
-}
 
-/** Create a server with the specified port, listen backlog,
-and local IP address to bind to.
-*/
-ServerSocket::ServerSocket(int port, int backlog, InetAddressPtr bindAddr)
+ServerSocket::~ServerSocket()
 {
-   socketImpl = new SocketImpl();
-   socketImpl->create(true);
-   socketImpl->bind(bindAddr, port);
-   socketImpl->listen(backlog);
 }
 
-ServerSocket::~ServerSocket()
-{
+void ServerSocket::close() {
+    synchronized sync(mutex);
+    if (socket != 0) {
+        apr_status_t status = apr_socket_close(socket);
+        if (status != APR_SUCCESS) {
+            throw SocketException(status);
+        }
+        socket = 0;
+    }
 }
 
 /** Listens for a connection to be made to this socket and
 accepts it
 */
-SocketPtr ServerSocket::accept()
-{
-   SocketImplPtr accepted = new SocketImpl;
-   socketImpl->accept(accepted);
-   return new Socket(accepted);
+SocketPtr ServerSocket::accept() {
+    synchronized sync(mutex);
+    if (socket == 0) {
+        throw IOException();
+    }
+    
+    apr_pollfd_t poll;
+    poll.p = pool.getAPRPool();
+    poll.desc_type = APR_POLL_SOCKET;
+    poll.reqevents = APR_POLLIN;
+    poll.rtnevents = 0;
+    poll.desc.s = socket;
+    poll.client_data = NULL;
+  
+    apr_int32_t signaled;
+    apr_interval_time_t to = timeout * 1000;
+    apr_status_t status = apr_poll(&poll, 1, &signaled, to);  
+  
+    if (APR_STATUS_IS_TIMEUP(status)) {
+        throw SocketTimeoutException();
+    } else if (status != APR_SUCCESS) {
+        throw SocketException(status);
+    }
+    
+    apr_pool_t* newPool;
+    status = apr_pool_create(&newPool, 0);
+    if (status != APR_SUCCESS) {
+        throw PoolException(status);
+    }
+    apr_socket_t* newSocket;
+    status = apr_socket_accept(&newSocket, socket, newPool);
+    if (status != APR_SUCCESS) {
+        apr_pool_destroy(newPool);
+        throw SocketException(status);
+    }
+    
+    status = apr_socket_opt_set(newSocket, APR_SO_NONBLOCK, 0);
+    if (status != APR_SUCCESS) {
+        apr_pool_destroy(newPool);
+        throw SocketException(status);
+    }
+    
+    return new Socket(newSocket, newPool);
 }
 
 /** Retrive setting for SO_TIMEOUT.
 */
 int ServerSocket::getSoTimeout() const
 {
-   return socketImpl->getSoTimeout();
+   return timeout;
 }
 
 /** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
 */
-void ServerSocket::setSoTimeout(int timeout)
+void ServerSocket::setSoTimeout(int newVal)
 {
-   socketImpl->setSoTimeout(timeout);
+   timeout = newVal;
 }
-

Modified: logging/log4cxx/trunk/src/main/cpp/socket.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/socket.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/socket.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/socket.cpp Fri Mar 28 02:52:44 2008
@@ -14,68 +14,117 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <log4cxx/logstring.h>
 #include <log4cxx/helpers/socket.h>
-#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/bytebuffer.h>
+#include <log4cxx/helpers/transcoder.h>
+#include "apr_network_io.h"
+#include "apr_signal.h"
+
 
 using namespace log4cxx;
 using namespace log4cxx::helpers;
 
 IMPLEMENT_LOG4CXX_OBJECT(Socket)
 
-/** Creates an unconnected socket.
-*/
-Socket::Socket() : socketImpl()
-{
-}
-
 /** Creates a stream socket and connects it to the specified port
 number at the specified IP address.
 */
-Socket::Socket(InetAddressPtr address, int port) : socketImpl(new SocketImpl())
+Socket::Socket(InetAddressPtr& address, int port) : pool(), socket(0), address(address), port(port) 
 {
-   socketImpl->create(true);
-   socketImpl->connect(address, port);
+  apr_status_t status =
+    apr_socket_create(&socket, APR_INET, SOCK_STREAM, 
+                      APR_PROTO_TCP, pool.getAPRPool());
+  if (status != APR_SUCCESS) {
+    throw SocketException(status);
+  }
+  
+  LOG4CXX_ENCODE_CHAR(host, address->getHostAddress());
+
+  // create socket address (including port)
+  apr_sockaddr_t *client_addr;
+  status =
+      apr_sockaddr_info_get(&client_addr, host.c_str(), APR_INET,
+                                  port, 0, pool.getAPRPool());
+  if (status != APR_SUCCESS) {
+      throw ConnectException(status);
+  }
+
+        // connect the socket
+  status =  apr_socket_connect(socket, client_addr);
+  if (status != APR_SUCCESS) {
+      throw ConnectException(status);
+  }
+}
+
+Socket::Socket(apr_socket_t* socket, apr_pool_t* pool) :
+    pool(pool, true), socket(socket) {
+    apr_sockaddr_t* sa;
+    apr_status_t status = apr_socket_addr_get(&sa, APR_REMOTE, socket);
+    if (status == APR_SUCCESS) {
+        port = sa->port;
+        LogString remotename;
+        LogString remoteip;
+        if (sa->hostname != NULL) {
+            Transcoder::decode(sa->hostname, remotename);
+        }
+        char* buf = 0;
+        status = apr_sockaddr_ip_get(&buf, sa);
+        if (status == APR_SUCCESS) {
+            Transcoder::decode(buf, remoteip);
+        }
+        address = new InetAddress(remotename, remoteip);
+    }
+}
+
+Socket::~Socket() {
+}
+
+size_t Socket::write(ByteBuffer& buf) {
+    if (socket == 0) {
+            throw ClosedChannelException();
+    }
+    int totalWritten = 0;
+    while(buf.remaining() > 0) {
+        apr_size_t written = buf.remaining();
+
+        // while writing to the socket, we need to ignore the SIGPIPE
+        // signal. Otherwise, when the client has closed the connection,
+        // the send() function would not return an error but call the
+        // SIGPIPE handler.
+#if APR_HAVE_SIGACTION
+        apr_sigfunc_t* old = apr_signal(SIGPIPE, SIG_IGN);
+        apr_status_t status = apr_socket_send(socket, buf.current(), &written);
+        apr_signal(SIGPIPE, old);
+#else
+        apr_status_t status = apr_socket_send(socket, buf.current(), &written);
+#endif
+        
+        buf.position(buf.position() + written);
+        totalWritten += written;
+        if (status != APR_SUCCESS) {
+            throw SocketException(status);
+        }
+    }
+    return totalWritten;
+}
+
+
+void Socket::close() {
+    if (socket != 0) {
+        apr_status_t status = apr_socket_close(socket);
+        if (status != APR_SUCCESS) {
+            throw SocketException(status);
+        }        
+        socket = 0;
+    }
 }
 
-/** Creates a socket and connects it to the specified remote
-address on the specified remote port.
-*/
-Socket::Socket(InetAddressPtr address, int port,
-   InetAddressPtr localAddr, int localPort) : socketImpl(new SocketImpl())
-{
-   socketImpl->create(true);
-   socketImpl->connect(address, port);
-   socketImpl->bind(localAddr, localPort);
+InetAddressPtr Socket::getInetAddress() const {
+    return address;
 }
 
-/** Creates an unconnected Socket
-with a user-specified SocketImpl.
-*/
-Socket::Socket(SocketImplPtr impl) : socketImpl(impl)
-{
+int Socket::getPort() const {
+    return port;
 }
 
-
-/** Creates a stream socket and connects it to the specified
-port number on the named host.
-*/
-Socket::Socket(const LogString& host, int port)
-   : socketImpl(new SocketImpl())
-{
-   socketImpl->create(true);
-   socketImpl->connect(host, port);
-}
-
-/**  Creates a socket and connects it to the specified remote
-host on the specified remote port.
-*/
-Socket::Socket(const LogString& host, int port,
-   InetAddressPtr localAddr, int localPort)
-        : socketImpl(new SocketImpl())
-{
-   socketImpl->create(true);
-   socketImpl->connect(host, port);
-   socketImpl->bind(localAddr, localPort);
-}
 

Modified: logging/log4cxx/trunk/src/main/cpp/sockethubappender.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/sockethubappender.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/sockethubappender.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/sockethubappender.cpp Fri Mar 28 02:52:44 2008
@@ -30,6 +30,7 @@
 #include <apr_thread_proc.h>
 #include <log4cxx/helpers/objectoutputstream.h>
 #include <log4cxx/helpers/socketoutputstream.h>
+#include <log4cxx/helpers/exception.h>
 
 using namespace log4cxx;
 using namespace log4cxx::helpers;
@@ -193,7 +194,6 @@
                 catch (InterruptedIOException&)
                 {
                         // timeout occurred, so just loop
-                        Thread::sleep(1000);
                 }
                 catch (SocketException& e)
                 {

Modified: logging/log4cxx/trunk/src/main/cpp/socketoutputstream.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/socketoutputstream.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/socketoutputstream.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/socketoutputstream.cpp Fri Mar 28 02:52:44 2008
@@ -39,7 +39,8 @@
 
 void SocketOutputStream::flush(Pool& /* p */) {
    if (array.size() > 0) {
-     socket->write(&array[0], array.size());
+     ByteBuffer buf(&array[0], array.size());
+     socket->write(buf);
      array.resize(0);
    }
 }

Modified: logging/log4cxx/trunk/src/main/cpp/syslogwriter.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/syslogwriter.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/syslogwriter.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/syslogwriter.cpp Fri Mar 28 02:52:44 2008
@@ -24,7 +24,6 @@
 #include <log4cxx/helpers/inetaddress.h>
 #include <log4cxx/helpers/datagramsocket.h>
 #include <log4cxx/helpers/datagrampacket.h>
-#include <log4cxx/helpers/socketimpl.h>
 #include <log4cxx/helpers/transcoder.h>
 
 #define SYSLOG_PORT 514

Modified: logging/log4cxx/trunk/src/main/cpp/telnetappender.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/telnetappender.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/telnetappender.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/telnetappender.cpp Fri Mar 28 02:52:44 2008
@@ -60,6 +60,7 @@
 {
         if (serverSocket == NULL) {
                 serverSocket = new ServerSocket(port);
+                serverSocket->setSoTimeout(1000);                
         }
         sh.run(acceptConnections, this);
 }
@@ -131,7 +132,8 @@
              iter++) {
              if (*iter != 0) {
                 try {
-                    (*iter)->write(buf.current(), buf.remaining());
+                    ByteBuffer b(buf.current(), buf.remaining());
+                    (*iter)->write(b);
                 } catch(Exception& ex) {
                     // The client has closed the connection, remove it from our list:
                     *iter = 0;
@@ -151,7 +153,7 @@
         while(msgIter != msg.end()) {
             encoder->encode(msg, msgIter, buf);
             buf.flip();
-            socket->write(buf.current(), buf.remaining());
+            socket->write(buf);
             buf.clear();
         }
 }
@@ -230,6 +232,10 @@
                         StringHelper::toString((int) count+1, p, oss);
                         oss += LOG4CXX_STR(" active connections)\r\n\r\n");
                         pThis->writeStatus(newClient, oss, p);
+                }
+        } catch(InterruptedIOException &e) {
+                if (pThis->closed) {
+                    return NULL;
                 }
         } catch(Exception& e) {
                 if (!pThis->closed) {

Modified: logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/helpers/exception.h Fri Mar 28 02:52:44 2008
@@ -207,6 +207,79 @@
                       IllegalStateException& operator=(const IllegalStateException&);
                 };
 
+                /** Thrown to indicate that there is an error in the underlying
+                protocol, such as a TCP error.
+                */
+                class LOG4CXX_EXPORT SocketException : public IOException
+                {
+                public:
+                        SocketException(const LogString& msg);
+                        SocketException(log4cxx_status_t status);
+                        SocketException(const SocketException&);
+                        SocketException& operator=(const SocketException&);
+                };
+
+                /** Signals that an error occurred while attempting to connect a socket
+                to a remote address and port. Typically, the connection was refused
+                remotely (e.g., no process is listening on the remote address/port).
+                */
+                class LOG4CXX_EXPORT ConnectException : public SocketException
+                {
+                public:
+                    ConnectException(log4cxx_status_t status);
+                    ConnectException(const ConnectException& src);
+                   ConnectException& operator=(const ConnectException&);
+                };
+
+                class LOG4CXX_EXPORT ClosedChannelException : public SocketException
+                {
+                public:
+                    ClosedChannelException();
+                    ClosedChannelException(const ClosedChannelException& src);
+                    ClosedChannelException& operator=(const ClosedChannelException&);
+                };
+
+                /** Signals that an error occurred while attempting to bind a socket to
+                a local address and port. Typically, the port is in use, or the
+                requested local address could not be assigned.
+                */
+                class LOG4CXX_EXPORT BindException : public SocketException
+                {
+                public:
+                      BindException(log4cxx_status_t status);
+                      BindException(const BindException&);
+                      BindException& operator=(const BindException&);
+                };
+               
+                /** Signals that an I/O operation has been interrupted. An
+                InterruptedIOException is thrown to indicate that an input or output
+                transfer has been terminated because the thread performing it was
+                interrupted. The field bytesTransferred  indicates how many bytes were
+                successfully transferred before the interruption occurred.
+                */
+                class LOG4CXX_EXPORT InterruptedIOException : public IOException
+                {
+                public:
+                     InterruptedIOException(const LogString& msg);
+                     InterruptedIOException(const InterruptedIOException&);
+                     InterruptedIOException& operator=(const InterruptedIOException&);
+                };
+
+               
+                /** Signals that an I/O operation has been interrupted. An
+                InterruptedIOException is thrown to indicate that an input or output
+                transfer has been terminated because the thread performing it was
+                interrupted. The field bytesTransferred  indicates how many bytes were
+                successfully transferred before the interruption occurred.
+                */
+                class LOG4CXX_EXPORT SocketTimeoutException : public InterruptedIOException
+                {
+                public:
+                     SocketTimeoutException();
+                     SocketTimeoutException(const SocketTimeoutException&);
+                     SocketTimeoutException& operator=(const SocketTimeoutException&);
+                };
+                 
 
         }  // namespace helpers
 } // namespace log4cxx

Modified: logging/log4cxx/trunk/src/main/include/log4cxx/helpers/serversocket.h
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/helpers/serversocket.h?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/helpers/serversocket.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/helpers/serversocket.h Fri Mar 28 02:52:44 2008
@@ -19,7 +19,7 @@
 #define _LOG4CXX_HELPERS_SERVER_SOCKET_H
 
 #include <log4cxx/helpers/socket.h>
-#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/mutex.h>
 
 namespace log4cxx
 {
@@ -32,18 +32,7 @@
                         */
                         ServerSocket(int port);
 
-                        /** Creates a server socket and binds it to the specified local
-                        port number, with the specified backlog.
-                        */
-                        ServerSocket(int port, int backlog);
-
-                        /** Create a server with the specified port, listen backlog,
-
-                        and local IP address to bind to.
-                        */
-                        ServerSocket(int port, int backlog, InetAddressPtr bindAddr);
-
-                        ~ServerSocket();
+                        virtual ~ServerSocket();
 
                         /** Listens for a connection to be made to this socket and
                         accepts it
@@ -52,24 +41,7 @@
 
                         /** Closes this socket.
                         */
-                        inline void close()
-                                { socketImpl->close(); }
-
-                        /** Returns the local address of this server socket.
-                        */
-                        inline InetAddressPtr getInetAddress() const
-                                { return socketImpl->getInetAddress(); }
-
-                        /** Returns the port on which this socket is listening.
-                        */
-                        inline int getLocalPort() const
-                                { return socketImpl->getLocalPort(); }
-
-                        /** Returns the implementation address and implementation
-                        port of this socket as a String
-                        */
-                        inline LogString toString() const
-                                { return socketImpl->toString(); }
+                        void close();
 
                         /** Retrive setting for SO_TIMEOUT.
                         */
@@ -78,9 +50,13 @@
                         /** Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds.
                         */
                         void setSoTimeout(int timeout);
-
-                protected:
-                        SocketImplPtr socketImpl;
+                        
+                private:
+                        Pool pool;
+                        Mutex mutex;
+                        apr_socket_t* socket;
+                        int timeout;
+                        
                 };
         }  // namespace helpers
 } // namespace log4cxx

Modified: logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socket.h
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socket.h?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socket.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socket.h Fri Mar 28 02:52:44 2008
@@ -18,16 +18,20 @@
 #ifndef _LOG4CXX_HELPERS_SOCKET_H
 #define _LOG4CXX_HELPERS_SOCKET_H
 
-#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/socketimpl.h>
+extern "C" {
+   struct apr_socket_t;
+}
+
+
+#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/pool.h>
+
 
 namespace log4cxx
 {
         namespace helpers
         {
-                class ServerSocker;
-
-
+                class ByteBuffer;                
                 /**
                 <p>This class implements client sockets (also called just "sockets"). A socket
                 is an endpoint for communication between two machines.
@@ -38,12 +42,6 @@
                 */
                 class LOG4CXX_EXPORT Socket : public helpers::ObjectImpl
                 {
-                friend class ServerSocket;
-                protected:
-                        /** Creates an unconnected socket.
-                        */
-                        Socket();
-
                 public:
                         DECLARE_ABSTRACT_LOG4CXX_OBJECT(Socket)
                         BEGIN_LOG4CXX_CAST_MAP()
@@ -53,58 +51,35 @@
                         /** Creates a stream socket and connects it to the specified port
                         number at the specified IP address.
                         */
-                        Socket(InetAddressPtr address, int port);
-
-                        /** Creates a socket and connects it to the specified remote
-                        address on the specified remote port.
-                        */
-                        Socket(InetAddressPtr address, int port,
-                                InetAddressPtr localAddr, int localPort);
-
-                protected:
-                        /** Creates an unconnected Socket
-                        with a user-specified SocketImpl.
-                        */
-                        Socket(SocketImplPtr impl);
+                        Socket(InetAddressPtr& address, int port);
+                        Socket(apr_socket_t* socket, apr_pool_t* pool);
+                        ~Socket();
 
-                public:
-                        /** Creates a stream socket and connects it to the specified
-                        port number on the named host.
-                        */
-                        Socket(const LogString& host, int port);
-
-                        /**  Creates a socket and connects it to the specified remote
-                        host on the specified remote port.
-                        */
-                        Socket(const LogString& host, int port,
-                                InetAddressPtr localAddr, int localPort);
-
-                        size_t read(void * buf, size_t len) const
-                                { return socketImpl->read(buf, len); }
-
-                        size_t write(const void * buf, size_t len)
-                                { return socketImpl->write(buf, len); }
+                        size_t write(ByteBuffer&);
 
                         /** Closes this socket. */
-                        void close()
-                                { socketImpl->close(); }
-
+                        void close();
+                                
                         /** Returns the value of this socket's address field. */
-                        inline InetAddressPtr getInetAddress() const
-                                { return socketImpl->getInetAddress(); }
-
-                        /** Returns the value of this socket's localport field. */
-                        inline int getLocalPort() const
-                                { return socketImpl->getLocalPort(); }
+                        InetAddressPtr getInetAddress() const;
 
                         /** Returns the value of this socket's port field. */
-                        inline int getPort() const
-                                { return socketImpl->getPort(); }
-
+                        int getPort() const;
                 private:
                         Socket(const Socket&);
                         Socket& operator=(const Socket&);
-                        SocketImplPtr socketImpl;
+                        
+                        Pool pool;
+                        
+                        apr_socket_t* socket;
+
+
+                       /** The IP address of the remote end of this socket. */
+                        InetAddressPtr address;
+
+                        /** The port number on the remote host to which
+                        this socket is connected. */
+                        int port;
                 };
                 
                 LOG4CXX_PTR_DEF(Socket);

Modified: logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socketoutputstream.h
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socketoutputstream.h?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socketoutputstream.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/helpers/socketoutputstream.h Fri Mar 28 02:52:44 2008
@@ -50,7 +50,7 @@
                         virtual void write(ByteBuffer& buf, Pool& p);
 
                 protected:
-                        LOG4CXX_LIST_DEF(ByteList, unsigned char);
+                        LOG4CXX_LIST_DEF(ByteList, char);
                         ByteList array;
                         SocketPtr socket;
 

Modified: logging/log4cxx/trunk/src/test/cpp/net/sockethubappendertestcase.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/test/cpp/net/sockethubappendertestcase.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/test/cpp/net/sockethubappendertestcase.cpp (original)
+++ logging/log4cxx/trunk/src/test/cpp/net/sockethubappendertestcase.cpp Fri Mar 28 02:52:44 2008
@@ -36,8 +36,9 @@
                 //
                 LOGUNIT_TEST(testDefaultThreshold);
                 LOGUNIT_TEST(testSetOptionThreshold);
-                LOGUNIT_TEST(testHello);
-
+                LOGUNIT_TEST(testActivateClose);
+                LOGUNIT_TEST(testActivateSleepClose);
+                LOGUNIT_TEST(testActivateWriteClose);
    LOGUNIT_TEST_SUITE_END();
 
 
@@ -46,14 +47,30 @@
         AppenderSkeleton* createAppenderSkeleton() const {
           return new log4cxx::net::SocketHubAppender();
         }
+
+        void testActivateClose() {
+            SocketHubAppenderPtr hubAppender(new SocketHubAppender());
+            Pool p;
+            hubAppender->activateOptions(p);
+            hubAppender->close();
+        }
+
+        void testActivateSleepClose() {
+            SocketHubAppenderPtr hubAppender(new SocketHubAppender());
+            Pool p;
+            hubAppender->activateOptions(p);
+            Thread::sleep(1000);
+            hubAppender->close();
+        }
+
         
-        void testHello() {
+        void testActivateWriteClose() {
             SocketHubAppenderPtr hubAppender(new SocketHubAppender());
             Pool p;
             hubAppender->activateOptions(p);
             LoggerPtr root(Logger::getRootLogger());
             root->addAppender(hubAppender);
-            for(int i = 0; i < 100; i++) {
+            for(int i = 0; i < 50; i++) {
                 LOG4CXX_INFO(root, "Hello, World " << i);
             }
             hubAppender->close();

Modified: logging/log4cxx/trunk/src/test/cpp/net/telnetappendertestcase.cpp
URL: http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/test/cpp/net/telnetappendertestcase.cpp?rev=642173&r1=642172&r2=642173&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/test/cpp/net/telnetappendertestcase.cpp (original)
+++ logging/log4cxx/trunk/src/test/cpp/net/telnetappendertestcase.cpp Fri Mar 28 02:52:44 2008
@@ -37,9 +37,9 @@
                 //
                 LOGUNIT_TEST(testDefaultThreshold);
                 LOGUNIT_TEST(testSetOptionThreshold);
-//
-//   TODO: test hangs on Ubuntu
-//                LOGUNIT_TEST(testActivateClose);
+                LOGUNIT_TEST(testActivateClose);
+                LOGUNIT_TEST(testActivateSleepClose);
+                LOGUNIT_TEST(testActivateWriteClose);
 
    LOGUNIT_TEST_SUITE_END();
 
@@ -57,12 +57,33 @@
             appender->setPort(TEST_PORT);
             Pool p;
             appender->activateOptions(p);
-            //
-            //   TODO: without the Thread::sleep, SocketImpl will NPE when trying to accept
-            //      connections on a closed socket.
+            appender->close();
+        }
+
+        void testActivateSleepClose() {
+            TelnetAppenderPtr appender(new TelnetAppender());
+            appender->setLayout(new TTCCLayout());
+            appender->setPort(TEST_PORT);
+            Pool p;
+            appender->activateOptions(p);
             Thread::sleep(1000);
             appender->close();
         }
+
+        void testActivateWriteClose() {
+            TelnetAppenderPtr appender(new TelnetAppender());
+            appender->setLayout(new TTCCLayout());
+            appender->setPort(TEST_PORT);
+            Pool p;
+            appender->activateOptions(p);
+            LoggerPtr root(Logger::getRootLogger());
+            root->addAppender(appender);
+            for (int i = 0; i < 50; i++) {
+                LOG4CXX_INFO(root, "Hello, World " << i);
+            }
+            appender->close();
+        }
+
 };
 
 LOGUNIT_TEST_SUITE_REGISTRATION(TelnetAppenderTestCase);