SL-17868 Crash at ThreadRecorder::bringUpToDate
According to bugsplat get_thread_recorder was null Replaced apr based LLThreadLocalPointer with thread_localmeow-7.2.2
parent
ebf7033f07
commit
fe26a9d32c
|
|
@ -108,7 +108,6 @@ set(llcommon_SOURCE_FILES
|
|||
llsys.cpp
|
||||
lltempredirect.cpp
|
||||
llthread.cpp
|
||||
llthreadlocalstorage.cpp
|
||||
llthreadsafequeue.cpp
|
||||
lltimer.cpp
|
||||
lltrace.cpp
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
#include "llapr.h"
|
||||
#include "llmutex.h"
|
||||
#include "apr_dso.h"
|
||||
#include "llthreadlocalstorage.h"
|
||||
|
||||
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
|
||||
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
|
||||
|
|
@ -54,7 +53,6 @@ void ll_init_apr()
|
|||
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
|
||||
}
|
||||
|
||||
LLThreadLocalPointerBase::initAllThreadLocalStorage();
|
||||
gAPRInitialized = true;
|
||||
}
|
||||
|
||||
|
|
@ -70,8 +68,6 @@ void ll_cleanup_apr()
|
|||
|
||||
LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL;
|
||||
|
||||
LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
|
||||
|
||||
if (gAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(gAPRPoolp);
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
#include <boost/noncopyable.hpp>
|
||||
#include "llwin32headerslean.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include "apr_getopt.h"
|
||||
#include "apr_signal.h"
|
||||
|
||||
#include "llstring.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,115 +0,0 @@
|
|||
/**
|
||||
* @file llthreadlocalstorage.cpp
|
||||
* @author Richard
|
||||
* @date 2013-1-11
|
||||
* @brief implementation of thread local storage utility classes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llthreadlocalstorage.h"
|
||||
#include "llapr.h"
|
||||
|
||||
//
|
||||
//LLThreadLocalPointerBase
|
||||
//
|
||||
bool LLThreadLocalPointerBase::sInitialized = false;
|
||||
|
||||
void LLThreadLocalPointerBase::set( void* value )
|
||||
{
|
||||
llassert(sInitialized && mThreadKey);
|
||||
|
||||
apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
|
||||
if (result != APR_SUCCESS)
|
||||
{
|
||||
ll_apr_warn_status(result);
|
||||
LL_ERRS() << "Failed to set thread local data" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void* LLThreadLocalPointerBase::get() const
|
||||
{
|
||||
// llassert(sInitialized);
|
||||
void* ptr;
|
||||
apr_status_t result =
|
||||
apr_threadkey_private_get(&ptr, mThreadKey);
|
||||
if (result != APR_SUCCESS)
|
||||
{
|
||||
ll_apr_warn_status(result);
|
||||
LL_ERRS() << "Failed to get thread local data" << LL_ENDL;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void LLThreadLocalPointerBase::initStorage( )
|
||||
{
|
||||
apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
|
||||
if (result != APR_SUCCESS)
|
||||
{
|
||||
ll_apr_warn_status(result);
|
||||
LL_ERRS() << "Failed to allocate thread local data" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLThreadLocalPointerBase::destroyStorage()
|
||||
{
|
||||
if (sInitialized)
|
||||
{
|
||||
if (mThreadKey)
|
||||
{
|
||||
apr_status_t result = apr_threadkey_private_delete(mThreadKey);
|
||||
if (result != APR_SUCCESS)
|
||||
{
|
||||
ll_apr_warn_status(result);
|
||||
LL_ERRS() << "Failed to delete thread local data" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLThreadLocalPointerBase::initAllThreadLocalStorage()
|
||||
{
|
||||
if (!sInitialized)
|
||||
{
|
||||
for (auto& base : instance_snapshot())
|
||||
{
|
||||
base.initStorage();
|
||||
}
|
||||
sInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
|
||||
{
|
||||
if (sInitialized)
|
||||
{
|
||||
//for (auto& base : instance_snapshot())
|
||||
//{
|
||||
// base.destroyStorage();
|
||||
//}
|
||||
sInitialized = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -30,100 +30,6 @@
|
|||
|
||||
#include "llinstancetracker.h"
|
||||
|
||||
class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
|
||||
{
|
||||
public:
|
||||
LLThreadLocalPointerBase()
|
||||
: mThreadKey(NULL)
|
||||
{
|
||||
if (sInitialized)
|
||||
{
|
||||
initStorage();
|
||||
}
|
||||
}
|
||||
|
||||
LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
|
||||
: mThreadKey(NULL)
|
||||
{
|
||||
if (sInitialized)
|
||||
{
|
||||
initStorage();
|
||||
}
|
||||
}
|
||||
|
||||
~LLThreadLocalPointerBase()
|
||||
{
|
||||
destroyStorage();
|
||||
}
|
||||
|
||||
static void initAllThreadLocalStorage();
|
||||
static void destroyAllThreadLocalStorage();
|
||||
|
||||
protected:
|
||||
void set(void* value);
|
||||
|
||||
void* get() const;
|
||||
|
||||
void initStorage();
|
||||
void destroyStorage();
|
||||
|
||||
protected:
|
||||
struct apr_threadkey_t* mThreadKey;
|
||||
static bool sInitialized;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class LLThreadLocalPointer : public LLThreadLocalPointerBase
|
||||
{
|
||||
public:
|
||||
|
||||
LLThreadLocalPointer()
|
||||
{}
|
||||
|
||||
explicit LLThreadLocalPointer(T* value)
|
||||
{
|
||||
set(value);
|
||||
}
|
||||
|
||||
|
||||
LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
|
||||
: LLThreadLocalPointerBase(other)
|
||||
{
|
||||
set(other.get());
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE T* get() const
|
||||
{
|
||||
return (T*)LLThreadLocalPointerBase::get();
|
||||
}
|
||||
|
||||
T* operator -> () const
|
||||
{
|
||||
return (T*)get();
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
return *(T*)get();
|
||||
}
|
||||
|
||||
LLThreadLocalPointer<T>& operator = (T* value)
|
||||
{
|
||||
set((void*)value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator ==(const T* other) const
|
||||
{
|
||||
if (!sInitialized) return false;
|
||||
return get() == other;
|
||||
}
|
||||
|
||||
bool isNull() const { return !sInitialized || get() == NULL; }
|
||||
|
||||
bool notNull() const { return sInitialized && get() != NULL; }
|
||||
};
|
||||
|
||||
template<typename DERIVED_TYPE>
|
||||
class LLThreadLocalSingletonPointer
|
||||
{
|
||||
|
|
@ -139,10 +45,10 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
static LL_THREAD_LOCAL DERIVED_TYPE* sInstance;
|
||||
static thread_local DERIVED_TYPE* sInstance;
|
||||
};
|
||||
|
||||
template<typename DERIVED_TYPE>
|
||||
LL_THREAD_LOCAL DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
|
||||
thread_local DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
|
||||
|
||||
#endif // LL_LLTHREADLOCALSTORAGE_H
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ StatBase::StatBase( const char* name, const char* description )
|
|||
mDescription(description ? description : "")
|
||||
{
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
if (LLTrace::get_thread_recorder().notNull())
|
||||
if (LLTrace::get_thread_recorder() != NULL)
|
||||
{
|
||||
LL_ERRS() << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << LL_ENDL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ void AccumulatorBufferGroup::makeCurrent()
|
|||
mStackTimers.makeCurrent();
|
||||
mMemStats.makeCurrent();
|
||||
|
||||
ThreadRecorder* thread_recorder = get_thread_recorder().get();
|
||||
ThreadRecorder* thread_recorder = get_thread_recorder();
|
||||
AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
|
||||
// update stacktimer parent pointers
|
||||
for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ Recording::~Recording()
|
|||
// allow recording destruction without thread recorder running,
|
||||
// otherwise thread shutdown could crash if a recording outlives the thread recorder
|
||||
// besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
|
||||
if (isStarted() && LLTrace::get_thread_recorder().notNull())
|
||||
if (isStarted() && LLTrace::get_thread_recorder() != NULL)
|
||||
{
|
||||
LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
|
||||
}
|
||||
|
|
@ -112,9 +112,9 @@ void Recording::update()
|
|||
|
||||
// must have
|
||||
llassert(mActiveBuffers != NULL
|
||||
&& LLTrace::get_thread_recorder().notNull());
|
||||
&& LLTrace::get_thread_recorder() != NULL);
|
||||
|
||||
if(!mActiveBuffers->isCurrent())
|
||||
if(!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL)
|
||||
{
|
||||
AccumulatorBufferGroup* buffers = mBuffers.write();
|
||||
LLTrace::get_thread_recorder()->deactivate(buffers);
|
||||
|
|
@ -144,7 +144,7 @@ void Recording::handleStart()
|
|||
mSamplingTimer.reset();
|
||||
mBuffers.setStayUnique(true);
|
||||
// must have thread recorder running on this thread
|
||||
llassert(LLTrace::get_thread_recorder().notNull());
|
||||
llassert(LLTrace::get_thread_recorder() != NULL);
|
||||
mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
|
||||
#endif
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ void Recording::handleStop()
|
|||
#if LL_TRACE_ENABLED
|
||||
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
|
||||
// must have thread recorder running on this thread
|
||||
llassert(LLTrace::get_thread_recorder().notNull());
|
||||
llassert(LLTrace::get_thread_recorder() != NULL);
|
||||
LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
|
||||
mActiveBuffers = NULL;
|
||||
mBuffers.setStayUnique(false);
|
||||
|
|
@ -1181,8 +1181,8 @@ void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& oth
|
|||
|
||||
PeriodicRecording& get_frame_recording()
|
||||
{
|
||||
static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED));
|
||||
return *sRecording;
|
||||
static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED);
|
||||
return sRecording;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,13 +308,13 @@ ThreadRecorder* get_master_thread_recorder()
|
|||
return sMasterThreadRecorder;
|
||||
}
|
||||
|
||||
LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
|
||||
ThreadRecorder*& get_thread_recorder_ptr()
|
||||
{
|
||||
static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
|
||||
static thread_local ThreadRecorder* s_thread_recorder;
|
||||
return s_thread_recorder;
|
||||
}
|
||||
|
||||
const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
|
||||
ThreadRecorder* get_thread_recorder()
|
||||
{
|
||||
return get_thread_recorder_ptr();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include "llmutex.h"
|
||||
#include "lltraceaccumulators.h"
|
||||
#include "llthreadlocalstorage.h"
|
||||
|
||||
namespace LLTrace
|
||||
{
|
||||
|
|
@ -92,7 +91,7 @@ namespace LLTrace
|
|||
|
||||
};
|
||||
|
||||
const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder();
|
||||
ThreadRecorder* get_thread_recorder();
|
||||
void set_thread_recorder(ThreadRecorder*);
|
||||
|
||||
void set_master_thread_recorder(ThreadRecorder*);
|
||||
|
|
|
|||
Loading…
Reference in New Issue