Author: carnold
Date: Fri Feb 15 13:51:36 2008
New Revision: 628179
URL: http://svn.apache.org/viewvc?rev=628179&view=rev
Log:
LOGCXX-117: Memory leak with ThreadSpecificData
Modified:
logging/log4cxx/trunk/src/main/cpp/loggingevent.cpp
logging/log4cxx/trunk/src/main/cpp/mdc.cpp
logging/log4cxx/trunk/src/main/cpp/ndc.cpp
logging/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp
logging/log4cxx/trunk/src/main/include/log4cxx/helpers/threadspecificdata.h
logging/log4cxx/trunk/src/main/include/log4cxx/ndc.h
Modified: logging/log4cxx/trunk/src/main/cpp/loggingevent.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/loggingevent.cpp?rev=628179&r1=628178&r2=628179&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/loggingevent.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/loggingevent.cpp Fri Feb 15 13:51:36 2008
@@ -144,12 +144,13 @@
}
else
{
- MDC::Map& m = ThreadSpecificData::getCurrentThreadMap();
+ ThreadSpecificData* data =
ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ MDC::Map& m = data->getMap();
- MDC::Map::const_iterator it;
- for (it = m.begin(); it != m.end(); it++)
- {
+ for(MDC::Map::const_iterator it = m.begin(); it !=
m.end(); it++) {
set.push_back(it->first);
+ }
}
}
@@ -162,8 +163,13 @@
{
mdcCopyLookupRequired = false;
// the clone call is required for asynchronous logging.
- mdcCopy = new
MDC::Map(ThreadSpecificData::getCurrentThreadMap());
- }
+ ThreadSpecificData* data =
ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ mdcCopy = new MDC::Map(data->getMap());
+ } else {
+ mdcCopy = new MDC::Map();
+ }
+ }
}
bool LoggingEvent::getProperty(const LogString& key, LogString& dest) const
Modified: logging/log4cxx/trunk/src/main/cpp/mdc.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/mdc.cpp?rev=628179&r1=628178&r2=628179&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/mdc.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/mdc.cpp Fri Feb 15 13:51:36 2008
@@ -42,8 +42,7 @@
void MDC::putLS(const LogString& key, const LogString& value)
{
- Map& map = ThreadSpecificData::getCurrentThreadMap();
- map[key] = value;
+ ThreadSpecificData::put(key, value);
}
void MDC::put(const std::string& key, const std::string& value)
@@ -55,12 +54,16 @@
bool MDC::get(const LogString& key, LogString& value)
{
- Map& map = ThreadSpecificData::getCurrentThreadMap();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Map& map = data->getMap();
- Map::iterator it = map.find(key);
- if (it != map.end()) {
+ Map::iterator it = map.find(key);
+ if (it != map.end()) {
value.append(it->second);
return true;
+ }
+ data->recycle();
}
return false;
}
@@ -78,13 +81,16 @@
bool MDC::remove(const LogString& key, LogString& value)
{
- Map::iterator it;
- Map& map = ThreadSpecificData::getCurrentThreadMap();
- if ((it = map.find(key)) != map.end())
- {
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Map& map = data->getMap();
+ Map::iterator it;
+ if ((it = map.find(key)) != map.end()) {
value = it->second;
map.erase(it);
+ data->recycle();
return true;
+ }
}
return false;
}
@@ -103,8 +109,12 @@
void MDC::clear()
{
- Map& map = ThreadSpecificData::getCurrentThreadMap();
- map.erase(map.begin(), map.end());
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Map& map = data->getMap();
+ map.erase(map.begin(), map.end());
+ data->recycle();
+ }
}
Modified: logging/log4cxx/trunk/src/main/cpp/ndc.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/ndc.cpp?rev=628179&r1=628178&r2=628179&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/ndc.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/ndc.cpp Fri Feb 15 13:51:36 2008
@@ -27,33 +27,6 @@
using namespace log4cxx;
using namespace log4cxx::helpers;
-NDC::DiagnosticContext::DiagnosticContext(const LogString& message1,
- const DiagnosticContext * parent)
- : fullMessage(message1), message(message1)
-{
- if (parent != 0)
- {
- fullMessage.insert(0, LOG4CXX_STR(" "));
- fullMessage.insert(0, parent->fullMessage);
- }
-}
-
-NDC::DiagnosticContext::~DiagnosticContext() {
-}
-
-NDC::DiagnosticContext::DiagnosticContext(const DiagnosticContext& src)
- : fullMessage(src.fullMessage), message(src.message) {
-}
-
-NDC::DiagnosticContext& NDC::DiagnosticContext::operator=(
- const DiagnosticContext& src)
-{
- message.assign(src.message);
- fullMessage.assign(src.fullMessage);
- return *this;
-}
-
-
NDC::NDC(const std::string& message)
{
push(message);
@@ -65,88 +38,118 @@
}
+LogString& NDC::getMessage(NDC::DiagnosticContext& ctx) {
+ return ctx.first;
+}
+
+LogString& NDC::getFullMessage(NDC::DiagnosticContext& ctx) {
+ return ctx.second;
+}
+
void NDC::clear()
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
while(!stack.empty()) {
stack.pop();
}
+ data->recycle();
+ }
}
bool NDC::get(LogString& dest)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
- if(!stack.empty())
- {
- dest.append(stack.top().fullMessage);
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ if(!stack.empty()) {
+ dest.append(getFullMessage(stack.top()));
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
-int NDC::getDepth()
-{
- return ThreadSpecificData::getCurrentThreadStack().size();
+int NDC::getDepth() {
+ int size = 0;
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ size = data->getStack().size();
+ if (size == 0) {
+ data->recycle();
+ }
+ }
+ return size;
}
LogString NDC::pop()
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
- LogString value(stack.top().message);
+ LogString value(getMessage(stack.top()));
stack.pop();
+ data->recycle();
return value;
}
- return LogString();
+ data->recycle();
+ }
+ return LogString();
}
bool NDC::pop(std::string& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ bool retval = false;
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
- Transcoder::encode(stack.top().message, dst);
+ Transcoder::encode(getMessage(stack.top()), dst);
stack.pop();
- return true;
+ retval = true;
}
- return false;
+ data->recycle();
+ }
+ return retval;
}
LogString NDC::peek()
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
- return stack.top().message;
+ return getMessage(stack.top());
}
- return LogString();
+ data->recycle();
+ }
+ return LogString();
}
bool NDC::peek(std::string& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
- Transcoder::encode(stack.top().message, dst);
+ Transcoder::encode(getMessage(stack.top()), dst);
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
void NDC::pushLS(const LogString& message)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
-
- if (stack.empty())
- {
- stack.push(DiagnosticContext(message, 0));
- }
- else
- {
- DiagnosticContext& parent = stack.top();
- stack.push(DiagnosticContext(message, &parent));
- }
+ ThreadSpecificData::push(message);
}
void NDC::push(const std::string& message)
@@ -161,8 +164,16 @@
}
bool NDC::empty() {
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
- return stack.empty();
+ bool empty = true;
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
+ empty = stack.empty();
+ if (empty) {
+ data->recycle();
+ }
+ }
+ return empty;
}
#if LOG4CXX_WCHAR_T_API
@@ -179,25 +190,34 @@
bool NDC::pop(std::wstring& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
- Transcoder::encode(stack.top().message, dst);
+ Transcoder::encode(getMessage(stack.top()), dst);
stack.pop();
+ data->recycle();
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
bool NDC::peek(std::wstring& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
- Transcoder::encode(stack.top().message, dst);
+ Transcoder::encode(getMessage(stack.top()), dst);
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
#endif
@@ -217,25 +237,34 @@
bool NDC::pop(std::basic_string<UniChar>& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
Transcoder::encode(stack.top().message, dst);
stack.pop();
+ data->recycle();
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
bool NDC::peek(std::basic_string<UniChar>& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
Transcoder::encode(stack.top().message, dst);
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
#endif
@@ -255,25 +284,34 @@
bool NDC::pop(CFStringRef& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
dst = Transcoder::encode(stack.top().message);
stack.pop();
+ data->recycle();
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
bool NDC::peek(CFStringRef& dst)
{
- Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ ThreadSpecificData* data = ThreadSpecificData::getCurrentData();
+ if (data != 0) {
+ Stack& stack = data->getStack();
if(!stack.empty())
{
dst = Transcoder::encode(stack.top().message);
return true;
}
- return false;
+ data->recycle();
+ }
+ return false;
}
#endif
Modified: logging/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp?rev=628179&r1=628178&r2=628179&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp (original)
+++ logging/log4cxx/trunk/src/main/cpp/threadspecificdata.cpp Fri Feb 15
13:51:36 2008
@@ -34,33 +34,85 @@
}
-log4cxx::NDC::Stack& ThreadSpecificData::getCurrentThreadStack() {
- return getCurrentData().ndcStack;
+log4cxx::NDC::Stack& ThreadSpecificData::getStack() {
+ return ndcStack;
}
-log4cxx::MDC::Map& ThreadSpecificData::getCurrentThreadMap() {
- return getCurrentData().mdcMap;
+log4cxx::MDC::Map& ThreadSpecificData::getMap() {
+ return mdcMap;
}
-ThreadSpecificData& ThreadSpecificData::getCurrentData() {
+ThreadSpecificData& ThreadSpecificData::getDataNoThreads() {
+ static ThreadSpecificData noThreadData;
+ return noThreadData;
+}
+
+ThreadSpecificData* ThreadSpecificData::getCurrentData() {
#if APR_HAS_THREADS
void* pData = NULL;
- apr_status_t stat = apr_threadkey_private_get(&pData,
APRInitializer::getTlsKey());
- if (stat != APR_SUCCESS) {
- throw ThreadException(stat);
- }
- if (pData == NULL) {
+ apr_threadkey_private_get(&pData, APRInitializer::getTlsKey());
+ return (ThreadSpecificData*) pData;
+#else
+ return &getDataNoThreads();
+#endif
+}
+
+void ThreadSpecificData::recycle() {
+ if(ndcStack.empty() && mdcMap.empty()) {
+ void* pData = NULL;
+ apr_status_t stat = apr_threadkey_private_get(&pData,
APRInitializer::getTlsKey());
+ if (stat == APR_SUCCESS && pData == this) {
+ stat = apr_threadkey_private_set(0, APRInitializer::getTlsKey());
+ if (stat == APR_SUCCESS) {
+ delete this;
+ }
+ }
+ }
+}
+
+void ThreadSpecificData::put(const LogString& key, const LogString& val) {
+ ThreadSpecificData* data = getCurrentData();
+ if (data == 0) {
+ data = createCurrentData();
+ }
+ if (data != 0) {
+ data->getMap().insert(log4cxx::MDC::Map::value_type(key, val));
+ }
+}
+
+
+
+
+void ThreadSpecificData::push(const LogString& val) {
+ ThreadSpecificData* data = getCurrentData();
+ if (data == 0) {
+ data = createCurrentData();
+ }
+ if (data != 0) {
+ NDC::Stack& stack = data->getStack();
+ if(stack.empty()) {
+ stack.push(NDC::DiagnosticContext(val, val));
+ } else {
+ LogString fullMessage(stack.top().second);
+ fullMessage.append(1, (logchar) 0x20);
+ fullMessage.append(val);
+ stack.push(NDC::DiagnosticContext(val, fullMessage));
+ }
+ }
+}
+
+
+
+ThreadSpecificData* ThreadSpecificData::createCurrentData() {
+#if APR_HAS_THREADS
ThreadSpecificData* newData = new ThreadSpecificData();
- stat = apr_threadkey_private_set(newData, APRInitializer::getTlsKey());
+ apr_status_t stat = apr_threadkey_private_set(newData,
APRInitializer::getTlsKey());
if (stat != APR_SUCCESS) {
delete newData;
- throw ThreadException(stat);
+ newData = NULL;
}
- return *newData;
- }
- return *((ThreadSpecificData*) pData);
+ return newData;
#else
- static ThreadSpecificData data;
- return data;
+ return 0;
#endif
}
Modified:
logging/log4cxx/trunk/src/main/include/log4cxx/helpers/threadspecificdata.h
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/helpers/threadspecificdata.h?rev=628179&r1=628178&r2=628179&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/helpers/threadspecificdata.h
(original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/helpers/threadspecificdata.h
Fri Feb 15 13:51:36 2008
@@ -36,11 +36,26 @@
ThreadSpecificData();
~ThreadSpecificData();
- static log4cxx::NDC::Stack& getCurrentThreadStack();
- static log4cxx::MDC::Map& getCurrentThreadMap();
+ /**
+ * Gets current thread specific data.
+ * @return thread specific data, may be null.
+ */
+ static ThreadSpecificData* getCurrentData();
+ /**
+ * Release this ThreadSpecficData if empty.
+ */
+ void recycle();
+
+ static void put(const LogString& key, const LogString&
val);
+ static void push(const LogString& val);
+
+ log4cxx::NDC::Stack& getStack();
+ log4cxx::MDC::Map& getMap();
+
private:
- static ThreadSpecificData& getCurrentData();
+ static ThreadSpecificData& getDataNoThreads();
+ static ThreadSpecificData* createCurrentData();
log4cxx::NDC::Stack ndcStack;
log4cxx::MDC::Map mdcMap;
};
Modified: logging/log4cxx/trunk/src/main/include/log4cxx/ndc.h
URL:
http://svn.apache.org/viewvc/logging/log4cxx/trunk/src/main/include/log4cxx/ndc.h?rev=628179&r1=628178&r2=628179&view=diff
==============================================================================
--- logging/log4cxx/trunk/src/main/include/log4cxx/ndc.h (original)
+++ logging/log4cxx/trunk/src/main/include/log4cxx/ndc.h Fri Feb 15 13:51:36
2008
@@ -98,21 +98,11 @@
*/
class LOG4CXX_EXPORT NDC
{
- private:
- class DiagnosticContext
- {
- public:
- LogString fullMessage;
- LogString message;
-
- DiagnosticContext(const LogString& message,
- const DiagnosticContext * parent);
- virtual ~DiagnosticContext();
- DiagnosticContext(const DiagnosticContext& src);
- DiagnosticContext& operator=(const DiagnosticContext&
src);
- };
-
public:
+ /**
+ * Pair of Message and FullMessage.
+ */
+ typedef std::pair<LogString, LogString> DiagnosticContext;
typedef std::stack<DiagnosticContext> Stack;
/**
@@ -265,6 +255,8 @@
private:
NDC(const NDC&);
NDC& operator=(const NDC&);
+ static LogString& getMessage(DiagnosticContext& ctx);
+ static LogString& getFullMessage(DiagnosticContext& ctx);
}; // class NDC;
} // namespace log4cxx