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

2019-03-02 23:43|来源: 网路

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

转自:http://www.cnblogs.com/pugang/archive/2012/04/26/2472135

相关问答

更多
  • EnumWindows列举了一个进程中的所有顶级窗口。 GetWindowThreadProcessId获取每个线程的进程和Id。 您现在有足够的信息来正常关闭任何GUI应用程序。 您可以将WM_CLOSE消息发送到您希望关闭的任何窗口。 许多窗口处理WM_CLOSE以提示用户保存文档。您可以使用PostThreadMessage向发现的线程发送WM_QUIT消息,以使消息循环终止。 不允许用户代码从不同的应用程序或线程调用DestroyWindow到窗口...如果应用程序不响应WM_CLOSE或WM_QU ...
  • 你需要注意fork的返回值。 对代码的这种小修改可能会满足您的需求。 #include #include #include #include struct process{ int pid; int bt; }; int main() { int no_of_process,i,new_process; printf("Enter the number of process\n"); ...
  • 我找到的答案是: 不,你无法在Windows中发出信号。 不,没有替代方法在openRTSP中编码。 窗口只构建#ifdefs输出信令代码。 一个名为Mutex的可能是编写相同功能的最简单方法。 The answers I have found are: No, you cannot signal in Windows. No, there is no alternative way coded in openRTSP. The windows build simply #ifdefs out the si ...
  • 您是否可能正在启动多个子进程并且只将SIGINT发送到您创建的最后一个子进程而不是之前的进程? 键入“PS”并在启动此程序后按Enter键,查看已启动的进程数。 I eventually did this : int startVideoRecording() { int error; error = 0; if ((AVRecordingProcess = fork()) != -1) { switch (AVRecordingProcess) { ...
  • 这里有两个主要问题: 第一个问题:如果你使用的是shell=True ,那么你正在杀死运行该进程的shell ,而不是进程本身。 在其父母遇害的情况下,儿童进程不复存在,不会立即死亡。 在你的情况下,你使用的是非内置的sleep ,所以你可以删除shell=True ,并且Popen会产生实际的进程ID: p.terminate()会起作用。 您可以(也应该)在大多数情况下避免使用shell=True ,即使它需要额外的python编码工作(将2个命令组合在一起,重定向输入/输出,所有这些情况都可以由一个或 ...
  • 操作系统将为您关闭文件描述符。 除非您有其他清理工作要做(例如写入文件或删除某些文件),否则使用未处理的终止信号(例如, SIGTERM或SIGINT )进行终止应该就足够了。 如果你还有其他的清理工作要做,请让孩子用父母信号处理器建立一个信号的父母信号(你需要用sigaction建立处理程序)。 这将使用返回码-1和errno == EINTR打破accept ,允许您做任何您需要做的事情。 volatile sig_atomic_t usr1 = 0; void usr1_handler(int Sig ...
  • 为此,您需要在您的过程对象和它们的名称之间存储映射 。 使用辅助函数可以使代码更易于阅读(IMO): def terminate(procname): return pmap[procname].terminate() if __name__ == '__main__': pmap = {} pname = "process-1" p = Process(target=f,name = pname, args=('bob',)) pmap[pname] = ...
  • 当剩下的唯一用户线程是守护进程线程时,JVM将终止。 查看您的线程转储,我们可以看到两个不是仍在运行的守护程序线程的线程: "pool-4-thread-1@5149" prio=5 tid=0x19 nid=NA waiting java.lang.Thread.State: WAITING at sun.misc.Unsafe.park(Unsafe.java:-1) at java.util.concurrent.locks.LockSupport.park(LockSup ...
  • 由于OSError:[Errno 1]操作不允许建议, 不允许终止该进程。 因为你使用了sudo ,所以杀死进程也应该实例化为sudo 。 也许你试试这个: import subprocess import os from tbselenium.tbdriver import TorBrowserDriver site = "check.torproject.org" try: process = subprocess.Popen(['sudo', 'tcpdump', '-l', '-i', ...
  • 真正的解决方案是处理原因而不是症状: 症状: run函数永远不会结束 原因:通信请求永远不会结束 大多数通信(输入)功能是可中断的,或具有本机超时。 如果您的通信例程没有本机超时,您可以(可能)使用alarm Posix调用将它们包装起来,该调用应该干净地中断它们并允许运行功能干净地退出。 您只需要注意alarm使用信号的情况,因此您不能阻止SIG_ALRM ,但您可以使用它来安装存储已被调用的地方的信号处理程序。 恕我直言,它将比使用std::terminate直接终止程序更简单,更清晰,更好地分离关注点 ...