Jump to content

Handles that never die


Recommended Posts

In my script, called SCRIPT, I call an external executable, called X, and read it's stdout. I invoke X with...

$handle = run ( "X.exe", "", @SW_HIDE, $STDOUT_CHILD )

Then SCRIPT reads every byte in the stream and then X closes, as expected.

SCRIPT repeats the above operation every 3 minutes for days, weeks, even months. The problem is that every time run() invokes X, 4 handles get created and only 2 of those handles "die" when X closes. The other 2 live until SCRIPT closes. Those 2 seem to begin life as named pipes and are renamed to Device\null after X closes. They don't die until SCRIPT exits. Obviously, since SCRIPT repeats the above operation every 3 minutes for many weeks, several thousand of these "orphaned" handles are left laying about doing nothing other than bothering the bejeezus out of me. And I have a strong feeling that one day Windows will run out of handles to assign to my dear SCRIPT and then it's all going to go KABLOOEY.

I know the 4 handles are opening but only 2 close because I see it in Process Explorer (PE) while SCRIPT runs. For those of you unfamiliar with process Process Explorer, it's a Task Manager replacement from Sys Internals (acquired by Microsoft 1 year ago). The handle count is viewable in PE's upper pane. If you open PE's lower pane and highlight SCRIPT in the upper pane then the details of the handles opening and closing and the names assigned to them are displayed in the lower pane along with many other details. PE shows the handles as type File.

Are the 2 orphaned handles unavoidable? Is this a bug in AutoIT? Or is that just the way it is in Windows? Is there any way to force the handles to close other than exiting SCRIPT? I suppose I could start SCRIPT in a second script that allows SCRIPT to run for a few hours then kills SCRIPT and restarts it.

BTW, I've tried FileClose($handle) after X closes but that does no good at all.

Link to comment
Share on other sites

You didn't show any code, so it isn't possible to sure this is your issue, but likely you didn't read everything out of the $STDOUT_CHILD pipe. Discussed here: handle/memory leak with Run/StdoutRead?, NOBUG

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

You didn't show any code, so it isn't possible to sure this is your issue, but likely you didn't read everything out of the $STDOUT_CHILD pipe. Discussed here: handle/memory leak with Run/StdoutRead?, NOBUG

:)

Thanks for directing me to that thread :P

I ran the last code snippet posted there and found that it leaks handles. I am not sure if the poster is saying that code snippet should work or not. Seems to me it should but it definitely leaks handles here. Anyway, see my script below. It runs hello.bat (see further down) which puts out 10 lines. My script reads hello.bat's stdout, adds a ! to the line and stores the line in $array. When it encounters EOF it stores a solitary ! char. Uncomment the _ArrayDisplay() line to see the contents of the array after it's full.

#include <Constants.au3>
#include <Array.au3>

    Opt("MustDeclareVars", 1)
    HotKeySet("{ESC}","Quit")

    dim $array[13]

    while 1
    
        fill_array($array)
    ;_ArrayDisplay($array)
    
        sleep(5000)

    wend

; =============================================================================
Func fill_array(byref $array)
    
    dim $count = 1
    dim $eos = false

    const $stream = Run("hello.bat", "" , "", $STDOUT_CHILD)
    
    sleep(1000)
    
    do
        
        $array[$count] = get_line($stream, $eos)
        $count = $count + 1
        
    until $eos

EndFunc
; =============================================================================
Func get_line(const $stream, byref $eos)

    dim $line = "", $char = ""

    do  
        
        $char = StdoutRead($stream,1)   ; Sets @error to non-zero if EOF is reached
        $eos = @error
        if $eos then msgbox(0, "", "End of stream", 5)
        if $char <> @cr and $char <> @lf  then $line = $line & $char
                                       
    until $char = @CR or $eos                 
                                   
    return $line & "!"

EndFunc
; =============================================================================
func quit()
    Exit
EndFunc
; =============================================================================

Below is the hello.bat

@echo off
echo Hello world
echo Hello world
echo Hello world
echo Hello world
echo Hello world
echo Hello world
echo Hello world
echo Hello world
echo Hello world
echo Hello world
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...