-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LOGCXX-431 #68
LOGCXX-431 #68
Changes from 11 commits
091a9ce
36e33e5
0b08d4e
60184d7
3687a8b
39bbf1b
6e725a7
46ad073
a82c4d9
187c181
a41756b
f728135
7d67642
1006b6f
c37d127
890c72f
2b232f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
include(FindThreads) | ||
|
||
try_compile(PTHREAD_SETNAME_NP_FOUND "${CMAKE_BINARY_DIR}/pthread-compile-tests" | ||
"${CMAKE_CURRENT_LIST_DIR}/test-pthread.cpp" | ||
LINK_LIBRARIES Threads::Threads ) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include <pthread.h> | ||
|
||
int main(){ | ||
pthread_t tid; | ||
pthread_setname_np(tid, "name"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
#include <apr_atomic.h> | ||
#include <log4cxx/helpers/transcoder.h> | ||
#include <log4cxx/helpers/exception.h> | ||
#include <log4cxx/helpers/threadutility.h> | ||
#include <functional> | ||
|
||
using namespace log4cxx; | ||
|
@@ -92,7 +93,7 @@ void FileWatchdog::start() | |
{ | ||
checkAndConfigure(); | ||
|
||
thread = std::thread( &FileWatchdog::run, this ); | ||
thread = ThreadUtility::instance()->createThread( LOG4CXX_STR("Filewatchdog"), &FileWatchdog::run, this ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
bool FileWatchdog::is_interrupted() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#include "log4cxx/helpers/threadutility.h" | ||
#include "log4cxx/private/log4cxx_private.h" | ||
#include "log4cxx/helpers/loglog.h" | ||
|
||
#include <signal.h> | ||
|
||
#if LOG4CXX_HAS_SETTHREADDESCRIPTION | ||
#include <windows.h> | ||
#include <processthreadsapi.h> | ||
#endif | ||
|
||
using log4cxx::helpers::ThreadUtility; | ||
|
||
struct ThreadUtility::priv_data{ | ||
ams-tschoening marked this conversation as resolved.
Show resolved
Hide resolved
|
||
priv_data(){ | ||
pre_start = nullptr; | ||
thread_start = nullptr; | ||
post_start = nullptr; | ||
} | ||
|
||
log4cxx::helpers::pre_thread_start pre_start; | ||
log4cxx::helpers::thread_started thread_start; | ||
log4cxx::helpers::post_thread_start post_start; | ||
}; | ||
ams-tschoening marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
ThreadUtility::ThreadUtility() : | ||
m_priv( new priv_data() ) | ||
{} | ||
|
||
ThreadUtility::~ThreadUtility(){} | ||
|
||
std::shared_ptr<ThreadUtility> ThreadUtility::instance(){ | ||
static std::shared_ptr<ThreadUtility> instance( new ThreadUtility() ); | ||
return instance; | ||
} | ||
|
||
void ThreadUtility::configureThreadFunctions( pre_thread_start pre_start1, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opinion: The phrase Opinion: |
||
thread_started started, | ||
post_thread_start post_start1 ){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that I had named things the same before; I can probably fix that easily enough. |
||
m_priv->pre_start = pre_start1; | ||
m_priv->thread_start = started; | ||
m_priv->post_start = post_start1; | ||
} | ||
|
||
void ThreadUtility::preThreadBlockSignals(){ | ||
#if LOG4CXX_HAS_PTHREAD_SIGMASK | ||
sigset_t set; | ||
sigfillset(&set); | ||
if( pthread_sigmask(SIG_SETMASK, &set, nullptr) < 0 ){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you want SIG_BLOCK (to be more explicit) here and store the old set somewhere.... |
||
LOGLOG_ERROR( LOG4CXX_STR("Unable to set thread sigmask") ); | ||
} | ||
#endif /* LOG4CXX_HAS_PTHREAD_SIGMASK */ | ||
} | ||
|
||
void ThreadUtility::threadStartedNameThread(LogString threadName, | ||
std::thread::id /*thread_id*/, | ||
std::thread::native_handle_type native_handle){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opinion: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at it again, I also realized that I had done cpp_style instead of JavaStyle for the function definitions as well. Since the rest of the library is all JavaStyle, I've made those updates as well. |
||
#if LOG4CXX_HAS_PTHREAD_SETNAME | ||
if( pthread_setname_np( static_cast<pthread_t>( native_handle ), threadName.c_str() ) < 0 ){ | ||
LOGLOG_ERROR( LOG4CXX_STR("unable to set thread name") ); | ||
} | ||
#elif LOG4CXX_HAS_SETTHREADDESCRIPTION | ||
HRESULT hr = SetThreadDescription(static_cast<HANDLE>(native_handle), threadName.c_str()); | ||
if(FAILED(hr)){ | ||
LOGLOG_ERROR( LOG4CXX_STR("unable to set thread name") ); | ||
} | ||
#endif | ||
} | ||
|
||
void ThreadUtility::postThreadUnblockSignals(){ | ||
#if LOG4CXX_HAS_PTHREAD_SIGMASK | ||
sigset_t set; | ||
sigemptyset(&set); | ||
if( pthread_sigmask(SIG_SETMASK, &set, nullptr) < 0 ){ | ||
LOGLOG_ERROR( LOG4CXX_STR("Unable to set thread sigmask") ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... so that you can restore the original sigmask afterwards.... |
||
} | ||
#endif /* LOG4CXX_HAS_PTHREAD_SIGMASK */ | ||
} | ||
|
||
|
||
log4cxx::helpers::pre_thread_start ThreadUtility::preStartFunction(){ | ||
return m_priv->pre_start; | ||
} | ||
|
||
log4cxx::helpers::thread_started ThreadUtility::threadStartedFunction(){ | ||
return m_priv->thread_start; | ||
} | ||
|
||
log4cxx::helpers::post_thread_start ThreadUtility::postStartFunction(){ | ||
return m_priv->post_start; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#ifndef _LOG4CXX_THREADUTILITY_H | ||
#define _LOG4CXX_THREADUTILITY_H | ||
|
||
#include <thread> | ||
#include <functional> | ||
#include <memory> | ||
|
||
#include "log4cxx/logstring.h" | ||
|
||
namespace log4cxx { | ||
namespace helpers { | ||
|
||
/** | ||
* A function that will be called before a thread is started. This can | ||
* be used to (for example) block all of the signals in the thread, so | ||
* that when the thread is created it will have a correct signal mask. | ||
*/ | ||
typedef std::function<void()> pre_thread_start; | ||
|
||
/** | ||
* Called when a new thread has started. This can be used to set | ||
* parameters for the thread in a platform-specific manner. | ||
* | ||
* @param threadName The name of the thread | ||
* @param thread_id The ID of the thread as reported by std::thread::get_id | ||
* @param native_handle The native handle of the thread, as reported by | ||
* std::thread::native_handle | ||
*/ | ||
typedef std::function<void( LogString threadName, | ||
std::thread::id thread_id, | ||
std::thread::native_handle_type native_handle )> thread_started; | ||
|
||
/** | ||
* Called after a thread has started. This can be used to (for example) | ||
* unblock the signals in the thread. | ||
*/ | ||
typedef std::function<void()> post_thread_start; | ||
|
||
class ThreadUtility; | ||
LOG4CXX_PTR_DEF(ThreadUtility); | ||
|
||
class LOG4CXX_EXPORT ThreadUtility { | ||
private: | ||
ThreadUtility(); | ||
|
||
log4cxx::helpers::pre_thread_start preStartFunction(); | ||
log4cxx::helpers::thread_started threadStartedFunction(); | ||
log4cxx::helpers::post_thread_start postStartFunction(); | ||
|
||
struct priv_data; | ||
std::unique_ptr<priv_data> m_priv; | ||
|
||
public: | ||
~ThreadUtility(); | ||
|
||
static std::shared_ptr<ThreadUtility> instance(); | ||
|
||
/** | ||
* Configure the thread functions that log4cxx will use. | ||
* Note that setting any of these parameters to nullptr is valid, | ||
* and simply results in the callback not being called. * | ||
*/ | ||
void configureThreadFunctions( pre_thread_start pre_start, | ||
thread_started started, | ||
post_thread_start post_start ); | ||
|
||
/** | ||
* A pre-start thread function that blocks signals to the new thread | ||
* (if the system has pthreads). If the system does not have pthreads, | ||
* is equivalent to preThreadDoNothing(); | ||
*/ | ||
void preThreadBlockSignals(); | ||
|
||
/** | ||
* A thread_started function that names the thread using the appropriate | ||
* system call. | ||
*/ | ||
void threadStartedNameThread(LogString threadName, | ||
std::thread::id thread_id, | ||
std::thread::native_handle_type native_handle); | ||
|
||
/** | ||
* A post-start thread function that unblocks signals that preThreadBlockSignals | ||
* blocked before starting the thread. If the system does not have pthreads, | ||
* is equivalent to postThreadDoNothing(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't find an implementation of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outdated comment; I originally had a method that did nothing, but then I realized that just testing the |
||
*/ | ||
void postThreadUnblockSignals(); | ||
|
||
/** | ||
* Start a thread | ||
*/ | ||
template<class Function, class... Args> | ||
std::thread createThread(LogString name, | ||
Function&& f, | ||
Args&&... args){ | ||
log4cxx::helpers::pre_thread_start pre_start = preStartFunction(); | ||
log4cxx::helpers::thread_started thread_start = threadStartedFunction(); | ||
log4cxx::helpers::post_thread_start post_start = postStartFunction(); | ||
|
||
if( pre_start ){ | ||
pre_start(); | ||
} | ||
std::thread t( f, args... ); | ||
if( thread_start ){ | ||
thread_start( name, | ||
t.get_id(), | ||
t.native_handle() ); | ||
} | ||
if( post_start ){ | ||
ams-tschoening marked this conversation as resolved.
Show resolved
Hide resolved
|
||
post_start(); | ||
} | ||
return t; | ||
} | ||
}; | ||
|
||
} /* namespace helpers */ | ||
} /* namespace log4cxx */ | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AyncAppend
vs.AsyncAppend
vs.AsyncAppender
vs.SocketAppend
... There's at least ans
missing.In general: Did you choose to not use the class name or should that simply be reused 1:1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Linux at least, the thread name is limited to 16 characters, so I wanted to keep the names as short as possible. At least in this case, there's enough space to do 'AsyncAppender'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't aware of the length limit, so your shorter names make perfectly sense. You are using them in most cases anyway already, no need to make it different here: