干干净净终结进程[转] Terminate process cleanly [reprint]

Terminate process cleanly[reprint]
I often noticed in the C examples I found on the net, that those examples made use of SafeTerminateProcess so I wondered what this call stands for and why they used it.
After some research I found an article which was from Dr Dobbs written somewhere around 1999 which explains the difficulties around TerminateProcess()
Just to mention a few of them:
Any application that does not have a console control handler or a message loop will not be able to react to the WM_CLOSE and will be killed via TerminateProcess().Deadlock in the message processing thread and using too small a timeout value in the call to WaitForSingleObject(), can cause TerminateProcess() to be used as well.It is generally a bad idea to call TerminateProcess() because the system does not shut down the process in an orderly fashion.Any DLLs used by the process will not receive the DLL_PROCESS_DETACH event, disk buffers are not properly flushed, and memory shared with other processes can be left in an inconsistent state.So what we can do now? Simple make a call to SafeTerminateProcess instead!
safetp.h — Declaration for SafeTerminateProcess()
/* Header file for SafeTerminateProcess */
#ifndef _SAFETP_H__ #define _SAFETP_H__
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode);
#endif
/* End of File */
 
SafeTerminateProcess() takes advantage of the fact that Win32′s ExitProcess() has a function signature compatible with that of a thread entry point. By “compatible,” I mean that the parameters of both function prototypes are the same type, but they have different return types. This lets me launch ExitProcess() in any process, using Win32′s CreateRemoteThread(), causing that process to perform an orderly shutdown.
 
The fact that ExitProcess() has a void return type while a thread function is expected to return a DWORD is not a problem. This just means that the exit code of the remote thread will be whatever happened to be in the return value register (EAX on 80×86 processors) when ExitProcess() finishes.
 
SafeTerminateProcess() has the same signature as TerminateProcess() and starts out by using DuplicateHandle() to ensure that it will have rights to create a thread in the remote process. Handles returned from CreateProcess() always have full privileges. 
SafeTerminateProcess() checks to make sure that the process is still running (no point in shooting a dead horse), and sets an appropriate GetLastError() value if it is not. If it is alive, I call CreateRemoteThread() with ExitProcess() as the entry point and pass SafeTerminateProcess()’s uExitCode parameter as the thread parameter. If the call fails for some reason, SafeTerminateProcess() saves the GetLastError() value so it can use it before returning.
/*
    Safely terminate a process by creating a remote thread
    in the process that calls ExitProcess
*/
#define STRICT
#include
BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
    DWORD dwTID, dwCode, dwErr = 0;
    HANDLE hProcessDup = INVALID_HANDLE_VALUE;
    HANDLE hRT = NULL;
    HINSTANCE hKernel = GetModuleHandle("Kernel32");
    BOOL bSuccess = FALSE;
    BOOL bDup = DuplicateHandle(GetCurrentProcess(),
                                hProcess,
                                GetCurrentProcess(),
                                &hProcessDup,
                                PROCESS_ALL_ACCESS,
                                FALSE,
                                0);
    // Detect the special case where the process is
    // already dead...
    if ( GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) &&
         (dwCode == STILL_ACTIVE) )
    {
        FARPROC pfnExitProc;
        pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
        hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess,
                                 NULL,
                                 0,
                                 (LPTHREAD_START_ROUTINE)pfnExitProc,
                                 (PVOID)uExitCode, 0, &dwTID);
        if ( hRT == NULL )
            dwErr = GetLastError();
    }
    else
    {
        dwErr = ERROR_PROCESS_ABORTED;
    }
    if ( hRT )
    {
        // Must wait process to terminate to
        // guarantee that it has exited...
        WaitForSingleObject((bDup) ? hProcessDup : hProcess,
                            INFINITE);
        CloseHandle(hRT);
        bSuccess = TRUE;
    }
    if ( bDup )
        CloseHandle(hProcessDup);
    if ( !bSuccess )
        SetLastError(dwErr);
    return bSuccess;
}
/* End of File */
References
[1] Case with TerminateProcess http://private-storm.de/2009/08/11/case-terminateprocess/
[2] Microsoft Knowledge Base Article #Q178893, HOWTO: Terminate an Application “Cleanly” in Win32,KB Q178893
[3] A Safer Alternative to TerminateProcess() Dr Dobbs
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值