diff options
Diffstat (limited to 'tests/stdlib/tfdleak.nim')
-rw-r--r-- | tests/stdlib/tfdleak.nim | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/tests/stdlib/tfdleak.nim b/tests/stdlib/tfdleak.nim index c4f144db5..5931be8c1 100644 --- a/tests/stdlib/tfdleak.nim +++ b/tests/stdlib/tfdleak.nim @@ -8,16 +8,41 @@ import os, osproc, strutils, nativesockets, net, selectors, memfiles, asyncdispatch, asyncnet when defined(windows): import winlean + + # Note: Windows 10-only API + proc compareObjectHandles(first, second: Handle): WINBOOL + {.stdcall, dynlib: "kernelbase", + importc: "CompareObjectHandles".} else: import posix proc leakCheck(f: AsyncFD | int | FileHandle | SocketHandle, msg: string, expectLeak = defined(nimInheritHandles)) = + var args = @[$f.int, msg, $expectLeak] + + when defined(windows): + var refFd: Handle + # NOTE: This function shouldn't be used to duplicate sockets, + # as this function may mess with the socket internal refcounting. + # but due to the lack of type segmentation in the stdlib for + # Windows (AsyncFD can be a file or a socket), we will have to + # settle with this. + # + # Now, as a poor solution for the refcounting problem, we just + # simply let the duplicated handle leak. This should not interfere + # with the test since new handles can't occupy the slot held by + # the leaked ones. + if duplicateHandle(getCurrentProcess(), f.Handle, + getCurrentProcess(), addr refFd, + 0, 1, DUPLICATE_SAME_ACCESS) == 0: + raiseOSError osLastError(), "Couldn't create the reference handle" + args.add $refFd + discard startProcess( getAppFilename(), - args = @[$f.int, msg, $expectLeak], + args = args, options = {poParentStreams} - ).waitForExit -1 + ).waitForExit proc isValidHandle(f: int): bool = ## Check if a handle is valid. Requires OS-native handles. @@ -72,7 +97,6 @@ proc main() = var mf = memfiles.open("__test_fdleak3", fmReadWrite, newFileSize = 1) defer: close mf when defined(windows): - leakCheck(mf.fHandle, "memfiles.open().fHandle", false) leakCheck(mf.mapHandle, "memfiles.open().mapHandle", false) else: leakCheck(mf.handle, "memfiles.open().handle", false) @@ -105,7 +129,20 @@ proc main() = fd = parseInt(paramStr 1) expectLeak = parseBool(paramStr 3) msg = (if expectLeak: "not " else: "") & "leaked " & paramStr 2 - if expectLeak xor fd.isValidHandle: + let validHandle = + when defined(windows): + # On Windows, due to the use of winlean, causes the program to open + # a handle to the various dlls that's loaded. This handle might + # collide with the handle sent for testing. + # + # As a walkaround, we pass an another handle that's purposefully leaked + # as a reference so that we can verify whether the "leaked" handle + # is the right one. + let refFd = parseInt(paramStr 4) + fd.isValidHandle and compareObjectHandles(fd, refFd) != 0 + else: + fd.isValidHandle + if expectLeak xor validHandle: echo msg when isMainModule: main() |