all groups > dotnet clr > september 2003 >
You're in the

dotnet clr

group:

CLR Bug Report: SetFunctionReJIT deadlocks


CLR Bug Report: SetFunctionReJIT deadlocks Patrick Grawehr
9/23/2003 5:45:21 PM
dotnet clr: Now I'm sure: There's a serious problem inside the CLR when calling
SetFunctionReJIT() on anything but the current method. Add (something like)
the following code as JITCompilationStarted callback in the profiler:

UINT g_testfunction=0;
STDMETHODIMP MyProfilerCallback::JITCompilationStarted(UINT functionId, BOOL
fIsSafeToBlock)
{
wchar_t wszClass[512];
wchar_t wszMethod[512];
wchar_t wszModule[512];
//Gona change this: The match will be on the metadata token,
//not on the name. It's easier and safer and faster.
//This is test code
if (g_testfunction!=0)
{
m_pProfilerInfo->SetFunctionReJIT(g_testfunction);
wprintf(L"Requesting rejit for %d.\n",g_testfunction);
g_testfunction=0;
}
wprintf(L" JIT: ");
if (GetMethodNameFromFunctionId(functionId, wszModule, wszClass, wszMethod))
{
wprintf(L"%ls!%ls::%ls as %d\n",wszModule,wszClass,wszMethod,functionId);
if (wcscmp(wszMethod,L"Test2")==0) //or some other method that is called at
least
//twice in the
test app.
g_testfunction=functionId;
}
else
{
wprintf(L"Couldn't resolve method name\n");
}

After this, use the profiler with a test application that calls the given
method at least twice, with some other call in between.

The clr then deadlocks and via the debugger you can see that
_CallDescrWorker has a problem with two stubs jumping to the beginning of
each other infinitelly.
With the Rotor-Code, I could get an Idea of what's wrong, but I'm not sure,
since the prestubs seem to be different in the .NET CLR implementation. I
suspect that there is a bug inside BOOL IJitManager::ForceReJIT(MethodDesc
*pFunction) and the provided code doesn't correctly set the method to
unjited.

If needed, I'll supply more information about this problem.

Patrick

RE: CLR Bug Report: SetFunctionReJIT deadlocks davidgut NO[at]SPAM online.microsoft.com
9/23/2003 10:41:45 PM
I've forwarded your mail on to some JIT experts here at Microsoft so they
can tak e look.
Thanks,
David
RE: CLR Bug Report: SetFunctionReJIT deadlocks Patrick Grawehr
9/24/2003 6:11:11 AM
davidgut@online.microsoft.com (David Gutierrez[MSFT]) wrote in
news:He5GfPigDHA.2332@cpmsftngxa06.phx.gbl:

[quoted text, click to view]

Hi!
Good news! I've found the bug.
[Remark: I'm presenting code from the rotor sources, but the bug applies
to the "default" clr too]
In codeman.cpp IJITManager::ForceReJIT, line 200.


const BYTE *pAddrOfCode = pFunction->GetAddrofCode();
if (UpdateableMethodStubManager::CheckIsStu(pAddrOfCode, NULL))
{
// Restore the RVA for the JIT.
ULONG dwRVA;
pFunction->GetMDImport()->GetMethodImplProps(pFunction->
GetMemberDef(),
&dwRVA, NULL);
pFunction->SetRVA(dwRVA);
// reset any flags relevant to the old code
pFunction->ClearFlagsOnUpdate();
// make our stub just jump to the prestub to force rejit
UpdateableMethodStubManager::UpdateStub( //<<--- HERE.
(Stub*)pAddrOfCode, pFunction->GetPreStubAddr());
}
This call to UpdateMethodStubManager::UpdateStub causes an infinite loop,
because pAddrOfCode contains the same as pFunction->GetPreStubAddr().
What actually needs to be done is to get pFunction->GetPreStubAddr() and
put
there a *call* [not a jmp] to the *global* prestub, not the one of the
function.
The global prestub address is stored in the variable g_preStub.
So we need to patch in 0xe8 and the four-byte relative address of
g_preStub.

Greetings.
Patrick

Re: CLR Bug Report: SetFunctionReJIT deadlocks Patrick Grawehr
9/24/2003 1:56:26 PM
Hi!
Good news! I've found the bug.
[Remark: I'm presenting code from the rotor sources, but the bug applies to
the "default" clr too]

In codeman.cpp IJITManager::ForceReJIT, line 200.
const BYTE *pAddrOfCode = pFunction->GetAddrofCode();
if (UpdateableMethodStubManager::CheckIsStub(pAddrOfCode, NULL))
{
// Restore the RVA for the JIT.
ULONG dwRVA;

pFunction->GetMDImport()->GetMethodImplProps(pFunction->GetMemberDef(),
&dwRVA, NULL);
pFunction->SetRVA(dwRVA);
// reset any flags relevant to the old code
pFunction->ClearFlagsOnUpdate();
// make our stub just jump to the prestub to force rejit
UpdateableMethodStubManager::UpdateStub( //<<--- HERE.
(Stub*)pAddrOfCode, pFunction->GetPreStubAddr());
}

This call to UpdateMethodStubManager::UpdateStub causes an infinite loop,
because pAddrOfCode contains the same as pFunction->GetPreStubAddr().
What actually needs to be done is to get pFunction->GetPreStubAddr() and put
there a *call* to the *global* prestub.
The global prestub address is stored in the variable g_preStub.
So we need to patch in 0xe8 and the four-byte relative address of g_preStub.

Patrick



"David Gutierrez[MSFT]" <davidgut@online.microsoft.com> schrieb im
Newsbeitrag news:He5GfPigDHA.2332@cpmsftngxa06.phx.gbl...
[quoted text, click to view]

RE: CLR Bug Report: SetFunctionReJIT deadlocks davidgut NO[at]SPAM online.microsoft.com
10/2/2003 9:53:56 PM
This will definitely help speed things along. Thanks!
David
AddThis Social Bookmark Button