GetThreadBacktraceContext leaves the given thread suspended
This commit is contained in:
@@ -28,7 +28,7 @@ void InitializeBacktrace();
|
|||||||
void GetBacktrace( const void **buf, size_t size, const BacktraceContext *ctx = NULL );
|
void GetBacktrace( const void **buf, size_t size, const BacktraceContext *ctx = NULL );
|
||||||
|
|
||||||
/* Set up a BacktraceContext to get a backtrace for a thread. ThreadID may
|
/* Set up a BacktraceContext to get a backtrace for a thread. ThreadID may
|
||||||
* not be the current thread. */
|
* not be the current thread. True is returned on success, false on failure. */
|
||||||
bool GetThreadBacktraceContext( int ThreadID, BacktraceContext *ctx );
|
bool GetThreadBacktraceContext( int ThreadID, BacktraceContext *ctx );
|
||||||
|
|
||||||
/* Set up a BacktraceContext to get a backtrace after receiving a signal, given
|
/* Set up a BacktraceContext to get a backtrace after receiving a signal, given
|
||||||
|
|||||||
@@ -151,46 +151,34 @@ int ResumeThread( int ThreadID )
|
|||||||
*
|
*
|
||||||
* tid() is a PID (from getpid) or a TID (from gettid). Note that this may have kernel compatibility
|
* tid() is a PID (from getpid) or a TID (from gettid). Note that this may have kernel compatibility
|
||||||
* problems, because NPTL is new and its interactions with ptrace() aren't well-defined.
|
* problems, because NPTL is new and its interactions with ptrace() aren't well-defined.
|
||||||
* If we're on a non-NPTL system, tid is a regular PID. */
|
* If we're on a non-NPTL system, tid is a regular PID.
|
||||||
|
*
|
||||||
|
* This call leaves the given thread suspended, so the returned context doesn't become invalid.
|
||||||
|
* ResumeThread() can be used to resume a thread after this call. */
|
||||||
bool GetThreadBacktraceContext( int ThreadID, BacktraceContext *ctx )
|
bool GetThreadBacktraceContext( int ThreadID, BacktraceContext *ctx )
|
||||||
{
|
{
|
||||||
/* Can't GetThreadBacktraceContext the current thread. */
|
/* Can't GetThreadBacktraceContext the current thread. */
|
||||||
ASSERT( ThreadID != GetCurrentThreadId() );
|
ASSERT( ThreadID != GetCurrentThreadId() );
|
||||||
|
|
||||||
/* Attach to the thread. */
|
/* Attach to the thread. This may fail with EPERM. This can happen for at least
|
||||||
int ret = PtraceAttach( ThreadID );
|
* two common reasons: the process might be in a debugger already, or *we* might
|
||||||
|
|
||||||
/* This may fail with EPERM. This can happen for at least two common
|
|
||||||
* reasons: the process might be in a debugger already, or *we* might
|
|
||||||
* already have attached to it via SuspendThread.
|
* already have attached to it via SuspendThread.
|
||||||
*
|
*
|
||||||
* If it's in a debugger, we won't be able to ptrace(PTRACE_GETREGS). If
|
* If it's in a debugger, we won't be able to ptrace(PTRACE_GETREGS). If
|
||||||
* it's us that attached, we will. Be careful: if SuspendThread was
|
* it's us that attached, we will. */
|
||||||
* called to stop the thread (causing this attach to fail), we must not
|
if( PtraceAttach( ThreadID ) == -1 )
|
||||||
* restart the thread when we're finished. */
|
|
||||||
bool bAttachFailed = (ret == -1);
|
|
||||||
if( bAttachFailed )
|
|
||||||
{
|
{
|
||||||
RAGE_ASSERT_M( errno == EPERM, ssprintf( "%s", strerror(errno) ) );
|
RAGE_ASSERT_M( errno == EPERM, ssprintf( "%s", strerror(errno) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
user_regs_struct regs;
|
user_regs_struct regs;
|
||||||
ret = ptrace( PTRACE_GETREGS, ThreadID, NULL, ®s );
|
if( ptrace( PTRACE_GETREGS, ThreadID, NULL, ®s ) == -1 )
|
||||||
if( ret != 0 )
|
return false;
|
||||||
ret = -1;
|
|
||||||
ASSERT( ret == 0 );
|
|
||||||
|
|
||||||
if( !bAttachFailed )
|
|
||||||
{
|
|
||||||
/* We attached to it, so we need to detach. */
|
|
||||||
ret = ptrace( PTRACE_DETACH, ThreadID, NULL, NULL );
|
|
||||||
ASSERT( ret == 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->pid = ThreadID;
|
ctx->pid = ThreadID;
|
||||||
ctx->eip = regs.eip;
|
ctx->eip = regs.eip;
|
||||||
ctx->esp = regs.esp;
|
ctx->esp = regs.esp;
|
||||||
ctx->ebp = regs.ebp;
|
ctx->ebp = regs.ebp;
|
||||||
|
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user