# HG changeset patch # Parent 69a165d8dc984cf1ad72d882370ebe818d0bf8ff diff -r 69a165d8dc98 Lib/test/regrtest.py --- a/Lib/test/regrtest.py Mon Jun 10 16:31:39 2013 +0100 +++ b/Lib/test/regrtest.py Mon Jun 10 16:56:23 2013 +0100 @@ -1412,19 +1412,25 @@ repcount = nwarmup + ntracked rc_deltas = [0] * repcount alloc_deltas = [0] * repcount + fd_deltas = [0] * repcount + handle_deltas = [0] * repcount print("beginning", repcount, "repetitions", file=sys.stderr) print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr) sys.stderr.flush() for i in range(repcount): indirect_test() - alloc_after, rc_after = dash_R_cleanup(fs, ps, pic, zdc, abcs) + alloc_after, rc_after, fd_after, handle_after = \ + dash_R_cleanup(fs, ps, pic, zdc, abcs) sys.stderr.write('.') sys.stderr.flush() if i >= nwarmup: rc_deltas[i] = rc_after - rc_before alloc_deltas[i] = alloc_after - alloc_before - alloc_before, rc_before = alloc_after, rc_after + fd_deltas[i] = fd_after - fd_before + handle_deltas[i] = handle_after - handle_before + alloc_before, rc_before, fd_before, handle_before = \ + alloc_after, rc_after, fd_after, handle_after print(file=sys.stderr) # These checkers return False on success, True on failure def check_rc_deltas(deltas): @@ -1437,10 +1443,17 @@ if not set(deltas) <= {1,0,-1}: return True return False + def check_fd_deltas(deltas): + return any(deltas) + def check_handle_deltas(deltas): + return abs(sum(deltas)) >= min(3, len(deltas)) failed = False for deltas, item_name, checker in [ (rc_deltas, 'references', check_rc_deltas), - (alloc_deltas, 'memory blocks', check_alloc_deltas)]: + (alloc_deltas, 'memory blocks', check_alloc_deltas), + (fd_deltas, 'fds', check_fd_deltas), + (handle_deltas, 'fds', check_handle_deltas), + ]: if checker(deltas): msg = '%s leaked %s %s, sum=%s' % ( test, deltas[nwarmup:], item_name, sum(deltas)) @@ -1452,6 +1465,32 @@ failed = True return failed +try: + MAXFD = os.sysconf("SC_OPEN_MAX") +except Exception: + MAXFD = 256 + +def _fdcount(): + """Count the number of open file descriptors""" + import errno + count = 0 + for i in range(MAXFD): + try: + newfd = os.dup(i) + except OSError as e: + if e.errno != errno.EBADF: + raise + else: + count += 1 + os.close(newfd) + return count + +if sys.platform == 'win32': + from _winapi import GetProcessHandleCount as _handlecount +else: + def _handlecount(): + return 0 + def dash_R_cleanup(fs, ps, pic, zdc, abcs): import gc, copyreg import _strptime, linecache @@ -1516,11 +1555,13 @@ else: ctypes._reset_cache() - # Collect cyclic trash and read memory statistics immediately after. + # Collect cyclic trash, read memory and fd statistics immediately after. func1 = sys.getallocatedblocks func2 = sys.gettotalrefcount + func3 = _fdcount + func4 = _handlecount gc.collect() - return func1(), func2() + return func1(), func2(), func3(), func4() def warm_caches(): # char cache diff -r 69a165d8dc98 Modules/_winapi.c --- a/Modules/_winapi.c Mon Jun 10 16:31:39 2013 +0100 +++ b/Modules/_winapi.c Mon Jun 10 16:56:23 2013 +0100 @@ -797,6 +797,29 @@ return PyUnicode_FromWideChar(filename, wcslen(filename)); } +PyDoc_STRVAR(GetProcessHandleCount_doc, +"GetProcessHandleCount([ProcessHandle]) -> HandleCount\n\ +\n\ +Return the number of open handles for the process specified\n\ +by ProcessHandle. If ProcessHandle is not given then the\n\ +handle count for the current process is given."); + +static PyObject * +winapi_GetProcessHandleCount(PyObject *self, PyObject *args) +{ + HANDLE Process = GetCurrentProcess(); + DWORD HandleCount; + + if (!PyArg_ParseTuple(args, "|" F_HANDLE ":GetProcessHandleCount", + &Process)) + return NULL; + + if (!GetProcessHandleCount(Process, &HandleCount)) + return PyErr_SetFromWindowsErr(0); + + return PyLong_FromUnsignedLong(HandleCount); +} + PyDoc_STRVAR(GetStdHandle_doc, "GetStdHandle(handle) -> integer\n\ \n\ @@ -1220,6 +1243,8 @@ GetCurrentProcess_doc}, {"GetModuleFileName", winapi_GetModuleFileName, METH_VARARGS, GetModuleFileName_doc}, + {"GetProcessHandleCount", winapi_GetProcessHandleCount, METH_VARARGS, + GetProcessHandleCount_doc}, {"GetStdHandle", winapi_GetStdHandle, METH_VARARGS, GetStdHandle_doc}, {"GetVersion", winapi_GetVersion, METH_VARARGS,