Extension Functions exposed by SOS

HRESULT

DumpMixedCallStack(

                           PDEBUG_CLIENT pClient,

                           PDEBUG_CONTROL pControl)

{

      // We can not use LoadLibrary Win32 API to load SOS.

      // To load an extension library (or to obtain a handle for an already loaded extension library), use AddExtension.

      // Son of strike is written as a DbgEng Extension, since it exports DebugExtensionInitialize.

 

      // SOS exports 4 extension function with its prefix as "_EFN_".

      // 1   44 00024960 _EFN_GetManagedExcepStack

      // 2   45 00022190 _EFN_GetManagedObjectFieldInfo

      // 3   46 00022070 _EFN_GetManagedObjectName

      // 4   47 00021FC0 _EFN_StackTrace

 

      HRESULT hr = S_OK;

 

      // Load extension library

      ULONG64  pHandle;

      hr = pControl->AddExtension("sos", 0, &pHandle);

 

      if(FAILED(hr))

      {

            goto cleanup;

      }

 

      typedef HRESULT (CALLBACK *FP_EFN_StackTrace)(PDEBUG_CLIENT Client, WCHAR wszTextOut[], UINT *puiTextLength, LPVOID pTransitionContexts, UINT *puiTransitionContextCount, UINT uiSizeOfContext, DWORD Flags);

      FP_EFN_StackTrace fp_efn_stacktrace = NULL;

 

      hr = pControl->GetExtensionFunction(pHandle, "StackTrace", (FARPROC *)&fp_efn_stacktrace);

 

      if (SUCCEEDED(hr) && fp_efn_stacktrace != NULL)

      {

            UINT puiTextLength;

            UINT puiTransitionContextCount;

            hr = fp_efn_stacktrace(pClient, NULL, &puiTextLength,

                  NULL, &puiTransitionContextCount, sizeof(CONTEXT), SOS_STACKTRACE_SHOWADDRESSES);

 

            WCHAR *stacksBuffer = new WCHAR[puiTextLength];

            CONTEXT* contextBuffer = new CONTEXT[puiTransitionContextCount];

 

            // Contexts for transition…

            hr = fp_efn_stacktrace(

                  pClient, stacksBuffer, &puiTextLength, contextBuffer,

                  &puiTransitionContextCount, sizeof(CONTEXT), SOS_STACKTRACE_SHOWADDRESSES); // print out esp and ebp.

 

            wprintf(L"%s\n", stacksBuffer);

 

            if (stacksBuffer != NULL)

            {

                  delete[] stacksBuffer;

            }

            if (contextBuffer != NULL)

            {

                  delete[] contextBuffer;

            }

      }

      else

            goto cleanup;

 

      // Unload extension library

      hr = pControl->RemoveExtension(pHandle);

      if(FAILED(hr))

      {

            goto cleanup;

      }

 

cleanup:

      return hr;

}

 

Austin.D

Unexpected ThreadAbortException Makes My Long Run WebService Aborts Unexpectedly

Sorry for the long, tedious, and a bit tongue twister title of this blog post. Since I struggled with it all this afternoon, it would be meaningful if I write down something here for future references.
 
The long run ASP.NET WebService is what I’m developing for our CER Symbol System enhancement. Although I don’t think WebService is born with dealing with long run tasks, we still chose to make the common functionalites exposed via it, because of it being the easiest way for us to program in a distributed way.
 
Everything was working fine when it ran on a local machine (I used to have some concern on time out issue, since the http runtime set request execution time out to 110 seconds. Hmm, it took almost an hour for each run, so it’s strange that HttpException with request time out is not thrown as I expected, instead, it throws ThreadAbortException), but it failed as long as we deployed and ran it on a stage server. According to the log file, the WebService failed due to a thrown unexpected ThreadAbortException.
 
ThreadAbortException is raised only when Thread.Abort is called. In ASP.NET there’re only 3 scenarios that we will get this exception: Request.Redirect(), Response.End() and Server.Transfer(). All of them use Thread Abort to shut down the processing of current page. But since none of these function callings appear in my code, so I infur this issue comes from the behavior of IIS.
 
In IIS, there are 2 configuration that may force to terminate the worker process, thun terminate all its threads: IIS pinging, rapid-fail protection. They both are designed for health checking purpose. You can find both settings under: Application Pools->Advanced Settings->Process Model and Rapid-Fail Protection.
 
For IIS pinging: IIS will repeatedly in a period send a ping message to worker process to make sure the worker process is currently responsive. If a worker process fails to reply in a maximum response time, IIS will try to shut down the worker process gracefully, and start a new one. Notice, there exists a "Shutdown time Limit", if worker process still does not reply and exceeds this time limitaion, IIS will then kill the worker process with calling Thread.Abort() for each threads. This is the case in my project.
 
For Rapid-Fail Protection: if IIS notices some worker process raises multiple errors within less than a failure interval period, it will then put this worker process in a rapid-fail protection mode, by means of which, this worker process will not have impact on other applications deployed on this same machine. IIS will also try to shut down this worker process, the behavior will be the same as above.
 
Tips: During the searching, I also find 2 very useful diagnostics methods.
1. Process Orphaning
As the name indicates, if it is enabled, when worker process is unstable, and stop response the ping message, IIS will give up managing this process, and let us to make determination on how to deal with it. In the Advanced Settings, we can see three entries for process orphaning, two of them are Executable and Executable Parameters. usually, we can set executable to a debugger, such as ntsd.exe or windbg.exe; set Executable parameters to "-g -p %1%". Thus, the specified debugger will attach to the unhealthy worker process, and take a snapshot of it (mini dump file).
 
2. In Rapid-Fail Protection, there are two similar configuration entries.
The uses of it is straight forward, as we can see from the description, it is the executable to run when an application pool is shut down by rapid fail protection. This could be used to configure a load balancer to redirect traffic for this application pool to another server.
 
Austin.D