This tutorial describes how to detect deadlocks in a child process of a service (or any descendant process of the service).
This tutorial covers the following:
Related tutorials:
Detecting deadlocks in a child process.
Detecting deadlocks in a service.
Detecting deadlocks in an IIS ISAPI DLL.
Detecting deadlocks for a child process from the command line.
This tutorial applies to all native applications and to mixed-mode applications where the startup code is native.
If your application is written entirely in .Net or .Net Core, or your application is mixed-mode with the startup code written in .Net or .Net core you can skip the part of this tutorial relating to the NT Service API and go straight to the detecting deadlocks in a service child process section.
Thread Validator ships with an example service and an example child process launched by the service. These can be found in the following directories in the Thread Validator installation directory:
or
or
The childProcess has already been modified to use the NT Service API. In this tutorial, we’ll describe the modifications you would make to the child process to make it work correctly with Thread Validator.
The NT Service API is a simple API that allows you to load the Thread Validator profiling DLL and start the process of detect deadlocks.
The API also includes some debugging functions to help provide debugging information via log files (the only way to get data out of a service without a connection to the Thread Validator user interface).
static void attachToThreadValidator() { if (bLogging) { // Set the log file name. // When anything goes wrong the API will write error information to this file. // You can also write to this log file any status errors you need (you'll see examples in this source file) svlTVStub_setLogFileName(SZLOGFILENAME); svlTVStub_deleteLogFile(); } if (bLogging) { svlTVStub_writeToLogFileW(L"About to load Thread Validator\r\n"); } SVL_SERVICE_ERROR errCode; #ifdef IS6432 // x86 with x64 GUI errCode = svlTVStub_LoadThreadValidator6432(); #else //#ifdef IS6432 // x86 with x86 GUI // x64 with x64 GUI errCode = svlTVStub_LoadThreadValidator(); #endif //#ifdef IS6432 if (bLogging) { if (errCode != SVL_OK) { DWORD lastError; lastError = GetLastError(); svlTVStub_writeToLogFileW(L"Thread Validator load failed. \r\n"); svlTVStub_writeToLogFileLastError(lastError); svlTVStub_writeToLogFile(errCode); svlTVStub_dumpPathToLogFile(); } else { svlTVStub_writeToLogFileW(L"Thread Validator load success. \r\n"); } } // DO NOT setup a service callback because this is a child application of a service, not a service // start Thread Validator errCode = svlTVStub_StartThreadValidator(); if (bLogging) { if (errCode != SVL_OK) { DWORD lastError; lastError = GetLastError(); svlTVStub_writeToLogFileW(L"Starting Thread Validator failed. \r\n"); svlTVStub_writeToLogFileLastError(lastError); svlTVStub_writeToLogFile(errCode); } svlTVStub_writeToLogFileW(L"Finished loading Thread Validator\r\n"); } }
Now that the NT Service API has been implemented in your application, we can start detect deadlocks in the service child process.
Select the application executable (the service’s child process) you are going to monitor. For this example the application is examples\serviceWithAChildProcess\serviceWithAChildProcess\x64\Release\childProcess_x64.exe.
There are a few things to check.
svlTVStub_setLogFileName(SZLOGFILENAME);
You have learned how to add the NT Service API to a native application that is going to be launched from a service, how to use Thread Validator to monitor a service’s child process, and what to look at to diagnose errors if things don’t work first time.