diff --git a/Readme.md b/Readme.md index ace54bf8..b9563996 100644 --- a/Readme.md +++ b/Readme.md @@ -36,6 +36,7 @@ - Build for .NET Framework 4.0 - Not overwriting log files when retrying to execute a package - Support sending custom messages on embedded pipe +- Best effort to log premature termination of companion process # WiX Toolset on GitHub The WiX Toolset builds Windows installation packages from XML source code. The toolset supports a command-line environment that developers may integrate into their build processes to build Windows Installer (MSI) packages and executable bundles. The WiX GitHub project hosts the WiX source code Git repositories. The following links will take you to more details: diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 0c601955..b7afc4f1 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp @@ -55,6 +55,9 @@ static void LogPackages( __in const BURN_RELATED_BUNDLES* pRelatedBundles, __in const BOOTSTRAPPER_ACTION action ); +static DWORD WINAPI MonitorCompanionProcess( + __in LPVOID lpParameter + ); // function definitions @@ -540,12 +543,47 @@ extern "C" HRESULT CoreElevate( hr = VariableSetNumeric(&pEngineState->variables, BURN_BUNDLE_ELEVATED, TRUE, TRUE); ExitOnFailure(hr, "Failed to overwrite the %ls built-in variable.", BURN_BUNDLE_ELEVATED); + + // Best effort to log premature termination of the process + pEngineState->companionConnection.hQuitRequested = ::CreateEvent(NULL, TRUE, FALSE, NULL); + if (pEngineState->companionConnection.hQuitRequested) + { + pEngineState->companionConnection.hQuitMonitorThread = ::CreateThread(NULL, 0, MonitorCompanionProcess, &pEngineState->companionConnection, 0, NULL); + } } LExit: return hr; } +static DWORD WINAPI MonitorCompanionProcess( + __in LPVOID lpParameter + ) +{ + BURN_PIPE_CONNECTION* pConnection = (BURN_PIPE_CONNECTION*)lpParameter; + HANDLE rghHandles[2] = { pConnection->hQuitRequested, pConnection->hProcess }; + DWORD dwRes = ERROR_SUCCESS; + HRESULT hr = S_OK; + + dwRes = ::WaitForMultipleObjects(ARRAYSIZE(rghHandles), rghHandles, FALSE, INFINITE); + switch (dwRes) + { + case WAIT_OBJECT_0: + hr = S_OK; + break; + case WAIT_OBJECT_0 + 1: + hr = E_SUSPECTED_AV_INTERFERENCE; + ExitOnFailure(hr, "Companion process has been terminated prematurely."); + break; + default: + ExitWithLastError(hr, "Failed to monitor proper termination of companion process."); + break; + } + +LExit: + return HRESULT_CODE(hr); +} + extern "C" HRESULT CoreApply( __in BURN_ENGINE_STATE* pEngineState, __in_opt HWND hwndParent diff --git a/src/burn/engine/pipe.cpp b/src/burn/engine/pipe.cpp index d21e278a..8ed7ed8e 100644 --- a/src/burn/engine/pipe.cpp +++ b/src/burn/engine/pipe.cpp @@ -60,6 +60,8 @@ void PipeConnectionUninitialize( { ReleaseFileHandle(pConnection->hCachePipe); ReleaseFileHandle(pConnection->hPipe); + ReleaseHandle(pConnection->hQuitRequested); + ReleaseHandle(pConnection->hQuitMonitorThread); ReleaseHandle(pConnection->hProcess); ReleaseStr(pConnection->sczSecret); ReleaseStr(pConnection->sczName); @@ -552,6 +554,11 @@ extern "C" HRESULT PipeTerminateChildProcess( HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; + + if (pConnection->hQuitRequested) + { + ::SetEvent(pConnection->hQuitRequested); + } // Prepare the exit message. hr = BuffWriteNumber(&pbData, &cbData, dwParentExitCode); diff --git a/src/burn/engine/pipe.h b/src/burn/engine/pipe.h index b03c11e8..2b5f64cc 100644 --- a/src/burn/engine/pipe.h +++ b/src/burn/engine/pipe.h @@ -26,6 +26,8 @@ typedef struct _BURN_PIPE_CONNECTION HANDLE hProcess; HANDLE hPipe; HANDLE hCachePipe; + HANDLE hQuitRequested; + HANDLE hQuitMonitorThread; } BURN_PIPE_CONNECTION; typedef enum _BURN_PIPE_MESSAGE_TYPE