Jump to content

StdoutRead() stops returning anything and doesn't set @error


VAN0
 Share

Recommended Posts

  • Developers

I guess all i was trying to tell you is that you should always end the loop when reading the stdout has an error. The others tests shouldn't be needed.

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

@Jos, exactly, that's why this topic created - without other tests it hangs the script...

There might be something wrong with StdoutRead()... every time it used it increases number of handles:

#include <Misc.au3>
Local $iSleep = 0 ; <==== if set to 1 it will not timeout
Local $iTimeout = 1000000 / ($iSleep * 10000 + 1), $iPrevTimer = 0
While 1
    If TimerDiff($iPrevTimer) > 1000 Then
        Local $sOut = "", $i = 0
        $iPrevTimer = TimerInit()
        Local $iPID = Run(@ComSpec & " /c WMIC PROCESS WHERE Name='autoit3.exe' GET handlecount", @SystemDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)
        ConsoleWrite(StringLeft("PID=" & ProcessExists($iPID) & "      ", 11))
        Do
            $i += 1
            Sleep($iSleep)
            $sOut &= StdoutRead($iPID)
        Until @error Or $i > $iTimeout
        StdioClose($iPID)
        Local $iClose = ProcessClose($iPID)
        ConsoleWrite(" loops=" & StringLeft($i & "       ", 8) & " close=" & $iClose & " error=" & @error & " out=" & StringStripWS($sOut, 4) & @CRLF)
    EndIf
    Sleep(100)
WEnd

 

Another thing, if Sleep(1) added into the loop, the issue seems to disappear, at least in my test without sleep it starts timeout after few seconds

Spoiler
>Running:(3.3.16.1):E:\Program Files\AutoIt3\autoit3.exe "E:\Program Files\AutoIt3\Scripts\vpn\test.au3"    
PID=119360  loops=80518    close=0 error=0 out=HandleCount 198 200 166 
PID=94344   loops=79281    close=0 error=0 out=HandleCount 198 202 166 
PID=30020   loops=80421    close=0 error=0 out=HandleCount 198 204 166
PID=125568  loops=1000001  close=0 error=0 out=
PID=81012   loops=1000001  close=0 error=0 out=

 

with Sleep(1) it hasn't timeout yet.

Edited by VAN0
Link to comment
Share on other sites

The minimum sleep time is 10 milliseconds, if you choose a value lower it will still be around at least 10ms.

#Region Main
    _ExecBatch("rasdial", 10)

    Func _ExecBatch($sCmd, $iCnt)
        Local Enum $ePid = 0, $eRslt, $eMax
        Local $arExec[$iCnt][$eMax]
        ; Process: start
        For $iExec = 0 To $iCnt - 1
            $arExec[$iExec][$ePid] = Run($sCmd, "", @SW_HIDE, $STDOUT_CHILD)
        Next

        ; Process: wait
        Local $iActive = 0
        Do
            $iActive = 0
            For $iExec = 0 To $iCnt - 1
                If ProcessExists($arExec[$iExec][$ePid]) Then $iActive += 1
            Next
        Until $iActive = 0

        ; Process: get data
        Local $iErrorCount = 0
        For $iExec = 0 To $iCnt - 1
            $arExec[$iExec][$eRslt] = StdoutRead($arExec[$iExec][$ePid])
            If @error Then $iErrorCount += 1
            StdioClose($arExec[$iExec][$ePid]) ; not sure if required
        Next

        ; Display data
        ;_ArrayDisplay($arExec)
        ConsoleWrite("Errors: " & $iErrorCount & @CRLF)
    EndFunc   ;==>_ExecBatch
#EndRegion Main

Can you try this approach? This will start rasdial 10 times (change it to any value you like) and will wait until all process are closed and will than read the data afterwards. I did run this for an hour without an issue and had 50 process startet at the same time.

Link to comment
Share on other sites

@HurleyShanabarger

The "process wait" loop exits when one process is still running, not when all of them are closed. And besides, as per original post, it works without issue when waited for the process to close.

Anyway, would you mind test code from my previous post, if you can reproduce the issue too? It's reproducible on my machine 100% after just a few seconds of running it.

At this point I'm not trying find a work around the issue but determine what actually causing it.

Link to comment
Share on other sites

I am pretty sure that the Process: wait loop is only left, when there is no process running anymore, that was started in the Process: start loop. Maybe you can explain that to me.

No really sure, what code I should run and test. The one from this post

is running. Best to provide a full script with instructions for testing.

Your script that is using WMIC is reading the handle count for all autoit3.exe processes. When running a script there should be some handles from the AutoIt wrapper. I changed my script, and it seems that not all handles are closed/released. But that still does not mean something is wrong with StdoutRead.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_UseX64=y
    #Tidy_Parameters=/reel /sf /ri
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#Region Main
    #include <Constants.au3>

    For $iExex = 1 To 10
        _ExecBatch("rasdial.exe", 10)
    Next

    Func _ExecBatch($sCmd, $iCnt)
        Local Enum $ePid = 0, $eRslt, $eMax
        Local $arExec[$iCnt][$eMax]
        ; Process: start
        RunWait(@ComSpec & " /c WMIC PROCESS WHERE ProcessId=" & @AutoItPID & " GET handlecount >Handle_1_BeforeProcessStarted.txt", @TempDir, @SW_HIDE)
        For $iExec = 0 To $iCnt - 1
            $arExec[$iExec][$ePid] = Run($sCmd, "", @SW_HIDE, $STDOUT_CHILD)
        Next

        ; Process: wait
        RunWait(@ComSpec & " /c WMIC PROCESS WHERE ProcessId=" & @AutoItPID & " GET handlecount >Handle_2_AfterProcessStarted.txt", @TempDir, @SW_HIDE)
        Local $iActive = 0
        Do
            $iActive = 0
            For $iExec = 0 To $iCnt - 1
                If ProcessExists($arExec[$iExec][$ePid]) Then $iActive += 1
            Next
        Until $iActive = 0
        RunWait(@ComSpec & " /c WMIC PROCESS WHERE ProcessId=" & @AutoItPID & " GET handlecount >Handle_3_AfterProcessClosed.txt", @TempDir, @SW_HIDE)

        ; Process: get data
        Local $iErrorCount = 0
        For $iExec = 0 To $iCnt - 1
            $arExec[$iExec][$eRslt] = StdoutRead($arExec[$iExec][$ePid])
            If @error Then $iErrorCount += 1
            StdioClose($arExec[$iExec][$ePid]) ; not sure if required
        Next
        RunWait(@ComSpec & " /c WMIC PROCESS WHERE ProcessId=" & @AutoItPID & " GET handlecount >Handle_4_AfterStdoutRead.txt", @TempDir, @SW_HIDE)

        ; Display data
        ConsoleWrite("Errors: " & $iErrorCount & @CRLF)
        ConsoleWrite("Handle_1_BeforeProcessStarted:" & @TAB & StringReplace(FileRead(@TempDir & "\Handle_1_BeforeProcessStarted.txt"), @CRLF, "") & @CRLF)
        ConsoleWrite("Handle_2_AfterProcessStarted: " & @TAB & StringReplace(FileRead(@TempDir & "\Handle_2_AfterProcessStarted.txt"), @CRLF, "") & @CRLF)
        ConsoleWrite("Handle_3_AfterProcessClosed:  " & @TAB & StringReplace(FileRead(@TempDir & "\Handle_3_AfterProcessClosed.txt"), @CRLF, "") & @CRLF)
        ConsoleWrite("Handle_4_AfterStdoutRead:     " & @TAB & StringReplace(FileRead(@TempDir & "\Handle_4_AfterStdoutRead.txt"), @CRLF, "") & @CRLF)
        ConsoleWrite("---------------------------------" & @CRLF)
        FileDelete(@TempDir & "\Handle_1_BeforeProcessStarted.txt")
        FileDelete(@TempDir & "\Handle_2_AfterProcessStarted.txt")
        FileDelete(@TempDir & "\Handle_3_AfterProcessClosed.txt")
        FileDelete(@TempDir & "\Handle_4_AfterStdoutRead.txt")
    EndFunc   ;==>_ExecBatch
#EndRegion Main

I am using @AutoItPid to just get the handles of the current process, my result looks like this

Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  163          
Handle_2_AfterProcessStarted:   HandleCount  194          
Handle_3_AfterProcessClosed:    HandleCount  194          
Handle_4_AfterStdoutRead:       HandleCount  174          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  174          
Handle_2_AfterProcessStarted:   HandleCount  204          
Handle_3_AfterProcessClosed:    HandleCount  204          
Handle_4_AfterStdoutRead:       HandleCount  184          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  184          
Handle_2_AfterProcessStarted:   HandleCount  214          
Handle_3_AfterProcessClosed:    HandleCount  214          
Handle_4_AfterStdoutRead:       HandleCount  194          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  194          
Handle_2_AfterProcessStarted:   HandleCount  224          
Handle_3_AfterProcessClosed:    HandleCount  224          
Handle_4_AfterStdoutRead:       HandleCount  204          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  204          
Handle_2_AfterProcessStarted:   HandleCount  234          
Handle_3_AfterProcessClosed:    HandleCount  234          
Handle_4_AfterStdoutRead:       HandleCount  214          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  214          
Handle_2_AfterProcessStarted:   HandleCount  244          
Handle_3_AfterProcessClosed:    HandleCount  244          
Handle_4_AfterStdoutRead:       HandleCount  224          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  224          
Handle_2_AfterProcessStarted:   HandleCount  254          
Handle_3_AfterProcessClosed:    HandleCount  254          
Handle_4_AfterStdoutRead:       HandleCount  234          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  234          
Handle_2_AfterProcessStarted:   HandleCount  264          
Handle_3_AfterProcessClosed:    HandleCount  264          
Handle_4_AfterStdoutRead:       HandleCount  244          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  244          
Handle_2_AfterProcessStarted:   HandleCount  274          
Handle_3_AfterProcessClosed:    HandleCount  274          
Handle_4_AfterStdoutRead:       HandleCount  254          
---------------------------------
Errors: 0
Handle_1_BeforeProcessStarted:  HandleCount  254          
Handle_2_AfterProcessStarted:   HandleCount  284          
Handle_3_AfterProcessClosed:    HandleCount  284          
Handle_4_AfterStdoutRead:       HandleCount  264          
---------------------------------

 

Link to comment
Share on other sites

38 minutes ago, HurleyShanabarger said:

I am pretty sure that the Process: wait loop is only left, when there is no process running anymore, that was started in the Process: start loop. Maybe you can explain that to me.

The If condition in the loop checks if process still exists, not if process doesn't exist. But that's half the issue, when one of the processes still exists it sets $iActive to non-zero, and the loop exits if $iActive is non-zero. It should've been checked if $iActive is equal to $iCnt

 

38 minutes ago, HurleyShanabarger said:

No really sure, what code I should run and test. The one from this post

Yes, unchanged code with WMIC, the out= should have numbers unless it's timedout

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...