-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[cdac] Implement IXCLRDataProcess::GetTaskByOSThreadID
#109230
Changes from 4 commits
2f62a35
2d593da
6b3ea64
e0bf5ec
aba9455
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,20 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
|
||
namespace Microsoft.Diagnostics.DataContractReader.Contracts; | ||
|
||
internal sealed class ThreadFactory : IContractFactory<IThread> | ||
{ | ||
IThread IContractFactory<IThread>.CreateContract(Target target, int version) | ||
{ | ||
TargetPointer threadStorePointer = target.ReadGlobalPointer(Constants.Globals.ThreadStore); | ||
TargetPointer threadStore = target.ReadPointer(threadStorePointer); | ||
return version switch | ||
{ | ||
1 => new Thread_1(target, threadStore), | ||
_ => default(Thread), | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Runtime.InteropServices.Marshalling; | ||
|
||
namespace Microsoft.Diagnostics.DataContractReader.Legacy; | ||
|
||
[GeneratedComClass] | ||
internal sealed unsafe partial class ClrDataTask : IXCLRDataTask | ||
{ | ||
private readonly TargetPointer _address; | ||
private readonly Target _target; | ||
private readonly IXCLRDataTask? _legacyImpl; | ||
|
||
public ClrDataTask(TargetPointer address, Target target, object? legacyImpl) | ||
{ | ||
_address = address; | ||
_target = target; | ||
_legacyImpl = legacyImpl as IXCLRDataTask; | ||
} | ||
|
||
public int GetProcess(/*IXCLRDataProcess*/ void** process) | ||
=> _legacyImpl is not null ? _legacyImpl.GetProcess(process) : HResults.E_NOTIMPL; | ||
public int GetCurrentAppDomain(/*IXCLRDataAppDomain*/ void** appDomain) | ||
=> _legacyImpl is not null ? _legacyImpl.GetCurrentAppDomain(appDomain) : HResults.E_NOTIMPL; | ||
public int GetUniqueID(ulong* id) | ||
=> _legacyImpl is not null ? _legacyImpl.GetUniqueID(id) : HResults.E_NOTIMPL; | ||
public int GetFlags(uint* flags) | ||
=> _legacyImpl is not null ? _legacyImpl.GetFlags(flags) : HResults.E_NOTIMPL; | ||
public int IsSameObject(IXCLRDataTask* task) | ||
=> _legacyImpl is not null ? _legacyImpl.IsSameObject(task) : HResults.E_NOTIMPL; | ||
public int GetManagedObject(/*IXCLRDataValue*/ void** value) | ||
=> _legacyImpl is not null ? _legacyImpl.GetManagedObject(value) : HResults.E_NOTIMPL; | ||
public int GetDesiredExecutionState(uint* state) | ||
=> _legacyImpl is not null ? _legacyImpl.GetDesiredExecutionState(state) : HResults.E_NOTIMPL; | ||
public int SetDesiredExecutionState(uint state) | ||
=> _legacyImpl is not null ? _legacyImpl.SetDesiredExecutionState(state) : HResults.E_NOTIMPL; | ||
public int CreateStackWalk(uint flags, /*IXCLRDataStackWalk*/ void** stackWalk) | ||
=> _legacyImpl is not null ? _legacyImpl.CreateStackWalk(flags, stackWalk) : HResults.E_NOTIMPL; | ||
public int GetOSThreadID(uint* id) | ||
=> _legacyImpl is not null ? _legacyImpl.GetOSThreadID(id) : HResults.E_NOTIMPL; | ||
public int GetContext(uint contextFlags, uint contextBufSize, uint* contextSize, byte* contextBuffer) | ||
=> _legacyImpl is not null ? _legacyImpl.GetContext(contextFlags, contextBufSize, contextSize, contextBuffer) : HResults.E_NOTIMPL; | ||
public int SetContext(uint contextSize, byte* context) | ||
=> _legacyImpl is not null ? _legacyImpl.SetContext(contextSize, context) : HResults.E_NOTIMPL; | ||
public int GetCurrentExceptionState(/*IXCLRDataExceptionState*/ void** exception) | ||
=> _legacyImpl is not null ? _legacyImpl.GetCurrentExceptionState(exception) : HResults.E_NOTIMPL; | ||
public int Request(uint reqCode, uint inBufferSize, byte* inBuffer, uint outBufferSize, byte* outBuffer) | ||
=> _legacyImpl is not null ? _legacyImpl.Request(reqCode, inBufferSize, inBuffer, outBufferSize, outBuffer) : HResults.E_NOTIMPL; | ||
public int GetName(uint bufLen, uint* nameLen, char* nameBuffer) | ||
=> _legacyImpl is not null ? _legacyImpl.GetName(bufLen, nameLen, nameBuffer) : HResults.E_NOTIMPL; | ||
public int GetLastExceptionState(/*IXCLRDataExceptionState*/ void** exception) | ||
=> _legacyImpl is not null ? _legacyImpl.GetLastExceptionState(exception) : HResults.E_NOTIMPL; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,56 @@ int IXCLRDataProcess.EndEnumTasks(ulong handle) | |
=> _legacyProcess is not null ? _legacyProcess.EndEnumTasks(handle) : HResults.E_NOTIMPL; | ||
|
||
int IXCLRDataProcess.GetTaskByOSThreadID(uint osThreadID, /*IXCLRDataTask*/ void** task) | ||
=> _legacyProcess is not null ? _legacyProcess.GetTaskByOSThreadID(osThreadID, task) : HResults.E_NOTIMPL; | ||
{ | ||
// Find the thread correspending to the OS thread ID | ||
Contracts.IThread contract = _target.Contracts.Thread; | ||
TargetPointer thread = contract.GetThreadStoreData().FirstThread; | ||
TargetPointer matchingThread = TargetPointer.Null; | ||
while (thread != TargetPointer.Null) | ||
{ | ||
Contracts.ThreadData threadData = contract.GetThreadData(thread); | ||
if (threadData.OSId.Value == osThreadID) | ||
{ | ||
matchingThread = thread; | ||
break; | ||
} | ||
|
||
thread = threadData.NextThread; | ||
} | ||
|
||
if (matchingThread == TargetPointer.Null) | ||
return HResults.E_INVALIDARG; | ||
|
||
ComWrappers cw = new StrategyBasedComWrappers(); | ||
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. Not for this PR specifically, but I've wondered in the past what this thing is and whether it's expensive 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. It's an implementation of That said, I think I must have been doing something weird when I was trying to switch the parameters |
||
|
||
int hr; | ||
nint legacyTaskPointer = 0; | ||
object? legacyTask = null; | ||
if (_legacyProcess is not null) | ||
{ | ||
hr = _legacyProcess.GetTaskByOSThreadID(osThreadID, (void**)&legacyTaskPointer); | ||
if (hr < 0) | ||
return hr; | ||
|
||
legacyTask = cw.GetOrCreateObjectForComInstance(legacyTaskPointer, CreateObjectFlags.None); | ||
} | ||
|
||
ClrDataTask taskObj = new(matchingThread, _target, legacyTask); | ||
|
||
// Lifetime is now managed via ClrDataTask | ||
if (legacyTaskPointer != 0) | ||
Marshal.Release(legacyTaskPointer); | ||
|
||
nint iunknownPtr = cw.GetOrCreateComInterfaceForObject(taskObj, CreateComInterfaceFlags.None); | ||
hr = Marshal.QueryInterface(iunknownPtr, typeof(IXCLRDataTask).GUID, out nint taskPtr); | ||
if (iunknownPtr != 0) | ||
Marshal.Release(iunknownPtr); | ||
|
||
if (hr == HResults.S_OK) | ||
*task = (IXCLRDataModule*)taskPtr; | ||
|
||
return hr; | ||
} | ||
|
||
int IXCLRDataProcess.GetTaskByUniqueID(ulong taskID, /*IXCLRDataTask*/ void** task) | ||
=> _legacyProcess is not null ? _legacyProcess.GetTaskByUniqueID(taskID, task) : HResults.E_NOTIMPL; | ||
|
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 kind of wanted to call this
ClrDataThread
, since I think that maps more clearly to what it is representing. But I stuck with matching theIXCLRDataTask
name and theIXCLRData*::GetTask*
APIs that return it (and also the name of the brittle DAC's implementation).