Skip to content

Commit 9659f08

Browse files
michieldwitteMichiel De Witte
and
Michiel De Witte
authored
Ensure messages are delivered by TelnetAppender when the socket is in a TIME_WAIT state (#495)
Co-authored-by: Michiel De Witte <[email protected]>
1 parent e620c2e commit 9659f08

File tree

8 files changed

+56
-3
lines changed

8 files changed

+56
-3
lines changed

src/main/cpp/aprserversocket.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ struct APRServerSocket::APRServerSocketPriv : public ServerSocketPrivate {
3535
apr_socket_t* socket;
3636
};
3737

38-
APRServerSocket::APRServerSocket(int port) :
38+
#if LOG4CXX_ABI_VERSION <= 15
39+
APRServerSocket::APRServerSocket(int port) :
40+
APRServerSocket(port, false) {}
41+
#endif
42+
43+
APRServerSocket::APRServerSocket(int port, bool reuseAddress) :
3944
ServerSocket(std::make_unique<APRServerSocketPriv>()){
4045
apr_status_t status =
4146
apr_socket_create(&_priv->socket, APR_INET, SOCK_STREAM,
@@ -53,6 +58,15 @@ APRServerSocket::APRServerSocket(int port) :
5358
throw SocketException(status);
5459
}
5560

61+
if (reuseAddress) {
62+
apr_status_t status = apr_socket_opt_set(_priv->socket, APR_SO_REUSEADDR, 1);
63+
64+
if (status != APR_SUCCESS)
65+
{
66+
throw SocketException(status);
67+
}
68+
}
69+
5670
// Create server socket address (including port number)
5771
apr_sockaddr_t* server_addr;
5872
status =

src/main/cpp/serversocket.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ void ServerSocket::setSoTimeout(int newVal)
5151
m_priv->timeout = newVal;
5252
}
5353

54+
#if LOG4CXX_ABI_VERSION <= 15
5455
ServerSocketUniquePtr ServerSocket::create(int port){
5556
return std::make_unique<APRServerSocket>(port);
5657
}
58+
#endif
59+
60+
ServerSocketUniquePtr ServerSocket::create(int port, bool reuseAddress){
61+
return std::make_unique<APRServerSocket>(port, reuseAddress);
62+
}

src/main/cpp/telnetappender.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct TelnetAppender::TelnetAppenderPriv : public AppenderSkeletonPrivate
5858
{ stopAcceptingConnections(); }
5959

6060
int port;
61+
bool reuseAddress = false;
6162
ConnectionList connections;
6263
LogString encoding;
6364
LOG4CXX_NS::helpers::CharsetEncoderPtr encoder;
@@ -112,7 +113,7 @@ void TelnetAppender::activateOptions(Pool& /* p */)
112113
{
113114
if (_priv->serverSocket == NULL)
114115
{
115-
_priv->serverSocket = ServerSocket::create(_priv->port);
116+
_priv->serverSocket = ServerSocket::create(_priv->port, _priv->reuseAddress);
116117
_priv->serverSocket->setSoTimeout(1000);
117118
}
118119

@@ -135,6 +136,10 @@ void TelnetAppender::setOption(const LogString& option,
135136
{
136137
setEncoding(value);
137138
}
139+
else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("REUSEADDRESS"), LOG4CXX_STR("reuseaddress")))
140+
{
141+
setReuseAddress(OptionConverter::toBoolean(value, true));
142+
}
138143
else
139144
{
140145
AppenderSkeleton::setOption(option, value);
@@ -358,6 +363,11 @@ void TelnetAppender::setMaxConnections(int newValue)
358363
}
359364
}
360365

366+
void TelnetAppender::setReuseAddress(bool reuseAddress)
367+
{
368+
_priv->reuseAddress = reuseAddress;
369+
}
370+
361371
bool TelnetAppender::requiresLayout() const
362372
{
363373
return false;

src/main/include/log4cxx/helpers/serversocket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,12 @@ class LOG4CXX_EXPORT ServerSocket
5757
*/
5858
void setSoTimeout(int timeout);
5959

60+
#if LOG4CXX_ABI_VERSION <= 15
6061
static ServerSocketUniquePtr create(int port);
62+
static ServerSocketUniquePtr create(int port, bool reuseAddress);
63+
#else
64+
static ServerSocketUniquePtr create(int port, bool reuseAddress = false);
65+
#endif
6166

6267
};
6368
} // namespace helpers

src/main/include/log4cxx/net/telnetappender.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ especially when monitoring a servlet remotely.
4242
4343
If no layout is provided, the log message only is sent to attached client(s).
4444
45+
The ReuseAddress option is disabled by default,
46+
enable it if you want it to be able to bind to the address immediately after restarting / crashing
47+
4548
See TelnetAppender::setOption() for the available options.
4649
4750
*/
@@ -96,6 +99,7 @@ class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
9699
Port | {int} | 23
97100
MaxConnections | {int} | 20
98101
Encoding | C,UTF-8,UTF-16,UTF-16BE,UTF-16LE,646,US-ASCII,ISO646-US,ANSI_X3.4-1968,ISO-8859-1,ISO-LATIN-1 | UTF-8
102+
ReuseAddress | True,False | True
99103
100104
\sa AppenderSkeleton::setOption()
101105
*/
@@ -125,6 +129,14 @@ class LOG4CXX_EXPORT TelnetAppender : public AppenderSkeleton
125129
*/
126130
void setMaxConnections(int newValue);
127131

132+
/**
133+
Set the SO_REUSEADDR option to of the server socket.
134+
This allows the socket to bind to an address that is in a TIME_WAIT state.
135+
This is useful for restarting immediately after it has been closed.
136+
137+
\sa setOption
138+
*/
139+
void setReuseAddress(bool reuseAddress);
128140

129141
/** Shutdown this appender. */
130142
void close() override;

src/main/include/log4cxx/private/aprserversocket.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ namespace helpers
3131
class LOG4CXX_EXPORT APRServerSocket : public helpers::ServerSocket
3232
{
3333
public:
34+
#if LOG4CXX_ABI_VERSION <= 15
3435
APRServerSocket(int port);
36+
APRServerSocket(int port, bool reuseAddress);
37+
#else
38+
APRServerSocket(int port, bool reuseAddress = false);
39+
#endif
3540

3641
void close() override;
3742

src/test/cpp/net/socketappendertestcase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class SocketAppenderTestCase : public AppenderSkeletonTestCase
8080
helpers::ServerSocketUniquePtr serverSocket;
8181
try
8282
{
83-
serverSocket = helpers::ServerSocket::create(tcpPort);
83+
serverSocket = helpers::ServerSocket::create(tcpPort, true);
8484
}
8585
catch (std::exception& ex)
8686
{

src/test/cpp/net/telnetappendertestcase.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class TelnetAppenderTestCase : public AppenderSkeletonTestCase
105105
TelnetAppenderPtr appender(new TelnetAppender());
106106
appender->setPort(TEST_PORT);
107107
appender->setMaxConnections(1);
108+
appender->setReuseAddress(true);
108109
Pool p;
109110
appender->activateOptions(p);
110111
LoggerPtr root(Logger::getRootLogger());

0 commit comments

Comments
 (0)