Greedo
Greedo

Reputation: 5543

WScript.Shell.Exec - Check if subprocess.stdout has data before synchronously reading

Context

I am using the following code to read stdout of a process launched with Wscript.Shell.Exec

Sub Main()
    Dim lspProcess As IWshExec = CreateObject("Wscript.Shell").Exec("deno lsp")
    Debug.Print readMessage(lspProcess)
End Sub

Function readMessage(lsp As IWshExec) As String
    Static contentLengthMatch As Object
    If contentLengthMatch Is Nothing Then
        Set contentLengthMatch = CreateObject("VBScript.RegExp")
        contentLengthMatch.IgnoreCase = True
        contentLengthMatch.Global = False
        contentLengthMatch.Pattern = "^Content-Length: (\d+)"
        'contentLengthMatch.Compile
    End If
    
    With lsp.StdOut
        Dim header As String = .ReadLine()
        Debug.Assert contentLengthMatch.Test(header) 'PERF: use mid
        Debug.Assert .ReadLine() = vbNullString 'swallow extra newline, could use skipline without the assert
        Dim contentLength As Long = Int(contentLengthMatch.Execute(header)(0).SubMatches(0))
        Return lsp.StdOut.Read(contentLength)
    End With
End Function

As you can see the process (lsp As IWshExec) is passed in and then my code looks for a particular message and returns the string it gets. The message has a header that looks like

Content-Length: 14

{"data":"foo"}

so it's possible to figure out how much more data to read with a single Read call.

Issue

The issue arises when I mistakenly call this readMessage function and there is no data in stdout. This then causes vba to hang indefinitely on the first .ReadLine() which is waiting for data that never comes, so crashes with no error message after becoming unresponsive.

I've tried various checks

Debug.Assert Not lsp.StdOut.AtEndOfStream
Debug.Assert Not lsp.StdOut.AtEndOfLine
Debug.Assert Not lsp.StdOut.Read(1) = vbNullString
Debug.Assert lsp.Status = vbRunning 'always true

However is seems any method that checks stdout is blocking until there is some data also causing the parent process to hang.

Upvotes: 0

Views: 39

Answers (0)

Related Questions