为什么这段代码在NULL句柄上调用CloseHandle?

时间:2012-06-02 23:39:34

标签: python c winapi

我正在尝试使用ctypes重新创建psutil项目(https://code.google.com/p/psutil/)上的一些功能。使用psutil对我想要的东西来说太过分了,这只是检查一个给定的pid当前是否正在运行。

我正在尝试重新创建的代码段是pid_is_running function

int
pid_is_running(DWORD pid)
{
    HANDLE hProcess;
    DWORD exitCode;

    // Special case for PID 0 System Idle Process
    if (pid == 0) {
        return 1;
    }

    if (pid < 0) {
        return 0;
    }

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                           FALSE, pid);
    if (NULL == hProcess) {
        // invalid parameter is no such process
        if (GetLastError() == ERROR_INVALID_PARAMETER) {
            CloseHandle(hProcess);
            return 0;
        }

        // access denied obviously means there's a process to deny access to...
        if (GetLastError() == ERROR_ACCESS_DENIED) {
            CloseHandle(hProcess);
            return 1;
        }

        CloseHandle(hProcess);
        PyErr_SetFromWindowsErr(0);
        return -1;
    }

    if (GetExitCodeProcess(hProcess, &exitCode)) {
        CloseHandle(hProcess);
        return (exitCode == STILL_ACTIVE);
    }

    // access denied means there's a process there so we'll assume it's running
    if (GetLastError() == ERROR_ACCESS_DENIED) {
        CloseHandle(hProcess);
        return 1;
    }

    PyErr_SetFromWindowsErr(0);
    CloseHandle(hProcess);
    return -1;
}

我不明白为什么代码正在关闭一个NULL句柄。这真的有必要吗?是错还是可能导致错误?

我也很感激到目前为止我能提出的任何意见

import os
import shlex
import subprocess
import ctypes as c
import ctypes.wintypes as w

PROCESS_QUERY_INFORMATION   = 0x0400L
PROCESS_VM_READ             = 0x0010L             
ERROR_INVALID_PARAMETER     = 0x57L
ERROR_ACCESS_DENIED         = 0x5L
STILL_ACTIVE                = 0x103L
FALSE                       = 0L

def start(cmd):
    l = shlex.split(cmd)
    return subprocess.Popen(l).pid

def get_pid(hProcess):
    pid = w.DWORD()
    return c.windll.kernel32.GetProcessId(hProcess);

def pid_is_running(pid):
    # adapted from psutil library 
    # http://code.google.com/searchframe#Dnjw9wRLlM4/trunk/psutil/arch/mswindows/process_info.c&q=pid_is_running%20package:psutil\.googlecode\.com&l=150

    pid         = w.DWORD(pid)
    hProcess    = w.HANDLE()

    if pid.value == 0L:
        return True

    if pid.value < 0L:
        return False

    flags = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
    hProcess = c.windll.kernel32.OpenProcess(flags, FALSE, pid)
    try:
        if 0 == hProcess:
            # invalid parameter is no such process
            last_error = c.windll.kernel32.GetLastError()
            if last_error == ERROR_INVALID_PARAMETER:
                return False

            # access denied obviously means there's a process to deny access to...
            if last_error == ERROR_ACCESS_DENIED:
                return True
            #return -1 #  Error? Should I throw an exception
            raise Exception('Could not find process and an error occurred')
        else:
            exitCode = w.DWORD()    
            if c.windll.kernel32.GetExitCodeProcess(hProcess, c.byref(exitCode)):
                return exitCode.value == STILL_ACTIVE

            # access denied means there's a process there so we'll assume it's running
            if c.windll.kernel32.GetLastError() == ERROR_ACCESS_DENIED:
                return True
            #return -1 #  Error? Should I throw an exception
            raise Exception('Process found and an error occurred')
    finally:
        if hProcess != 0:
            c.windll.kernel32.CloseHandle(hProcess)

1 个答案:

答案 0 :(得分:1)

可能会自动生成每个返回路径关闭它。即使是C程序员也没有足够的愚蠢来在每条路径上释放资源,他们使用的是基于goto的清理习惯。

当然,

  

针对未在API中公开的ntdll函数进行编译

可能表示该代码使用内部NT API函数,这些函数必将在以后的任何时候更改并破坏lolsies的代码。