Exposed process file handles in osproc module.
The file handles of a PProcess instance can now be accessed through the inputHandle(), outputHandle(), and errorHandle() methods. Also tidied up documentation for stream accessor procs a bit.
This commit is contained in:
parent
2555e500b6
commit
f103cb4538
1 changed files with 58 additions and 34 deletions
|
|
@ -24,10 +24,10 @@ type
|
||||||
TProcess = object of TObject
|
TProcess = object of TObject
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
FProcessHandle: Thandle
|
FProcessHandle: Thandle
|
||||||
inputHandle, outputHandle, errorHandle: TFileHandle
|
inHandle, outHandle, errHandle: TFileHandle
|
||||||
id: THandle
|
id: THandle
|
||||||
else:
|
else:
|
||||||
inputHandle, outputHandle, errorHandle: TFileHandle
|
inHandle, outHandle, errHandle: TFileHandle
|
||||||
inStream, outStream, errStream: PStream
|
inStream, outStream, errStream: PStream
|
||||||
id: TPid
|
id: TPid
|
||||||
exitCode: cint
|
exitCode: cint
|
||||||
|
|
@ -113,23 +113,47 @@ proc peekExitCode*(p: PProcess): int {.tags: [].}
|
||||||
## return -1 if the process is still running. Otherwise the process' exit code
|
## return -1 if the process is still running. Otherwise the process' exit code
|
||||||
|
|
||||||
proc inputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
|
proc inputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
|
||||||
## returns ``p``'s input stream for writing to
|
## returns ``p``'s input stream for writing to.
|
||||||
##
|
##
|
||||||
## **Warning**: The returned `PStream` should not be closed manually as it
|
## **Warning**: The returned `PStream` should not be closed manually as it
|
||||||
## is closed when closing the PProcess ``p``.
|
## is closed when closing the PProcess ``p``.
|
||||||
|
|
||||||
proc outputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
|
proc outputStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
|
||||||
## returns ``p``'s output stream for reading from
|
## returns ``p``'s output stream for reading from.
|
||||||
##
|
##
|
||||||
## **Warning**: The returned `PStream` should not be closed manually as it
|
## **Warning**: The returned `PStream` should not be closed manually as it
|
||||||
## is closed when closing the PProcess ``p``.
|
## is closed when closing the PProcess ``p``.
|
||||||
|
|
||||||
proc errorStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
|
proc errorStream*(p: PProcess): PStream {.rtl, extern: "nosp$1", tags: [].}
|
||||||
## returns ``p``'s output stream for reading from
|
## returns ``p``'s error stream for reading from.
|
||||||
##
|
##
|
||||||
## **Warning**: The returned `PStream` should not be closed manually as it
|
## **Warning**: The returned `PStream` should not be closed manually as it
|
||||||
## is closed when closing the PProcess ``p``.
|
## is closed when closing the PProcess ``p``.
|
||||||
|
|
||||||
|
proc inputHandle*(p: PProcess): TFileHandle {.rtl, extern: "nosp$1",
|
||||||
|
tags: [].} =
|
||||||
|
## returns ``p``'s input file handle for writing to.
|
||||||
|
##
|
||||||
|
## **Warning**: The returned `TFileHandle` should not be closed manually as
|
||||||
|
## it is closed when closing the PProcess ``p``.
|
||||||
|
result = p.inHandle
|
||||||
|
|
||||||
|
proc outputHandle*(p: PProcess): TFileHandle {.rtl, extern: "nosp$1",
|
||||||
|
tags: [].} =
|
||||||
|
## returns ``p``'s output file handle for reading from.
|
||||||
|
##
|
||||||
|
## **Warning**: The returned `TFileHandle` should not be closed manually as
|
||||||
|
## it is closed when closing the PProcess ``p``.
|
||||||
|
result = p.outHandle
|
||||||
|
|
||||||
|
proc errorHandle*(p: PProcess): TFileHandle {.rtl, extern: "nosp$1",
|
||||||
|
tags: [].} =
|
||||||
|
## returns ``p``'s error file handle for reading from.
|
||||||
|
##
|
||||||
|
## **Warning**: The returned `TFileHandle` should not be closed manually as
|
||||||
|
## it is closed when closing the PProcess ``p``.
|
||||||
|
result = p.errHandle
|
||||||
|
|
||||||
when defined(macosx) or defined(bsd):
|
when defined(macosx) or defined(bsd):
|
||||||
const
|
const
|
||||||
CTL_HW = 6
|
CTL_HW = 6
|
||||||
|
|
@ -339,16 +363,16 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
HE = HO
|
HE = HO
|
||||||
else:
|
else:
|
||||||
CreatePipeHandles(HE, Si.hStdError)
|
CreatePipeHandles(HE, Si.hStdError)
|
||||||
result.inputHandle = TFileHandle(hi)
|
result.inHandle = TFileHandle(hi)
|
||||||
result.outputHandle = TFileHandle(ho)
|
result.outHandle = TFileHandle(ho)
|
||||||
result.errorHandle = TFileHandle(he)
|
result.errHandle = TFileHandle(he)
|
||||||
else:
|
else:
|
||||||
SI.hStdError = GetStdHandle(STD_ERROR_HANDLE)
|
SI.hStdError = GetStdHandle(STD_ERROR_HANDLE)
|
||||||
SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
|
SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
|
||||||
SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
|
SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
result.inputHandle = TFileHandle(si.hStdInput)
|
result.inHandle = TFileHandle(si.hStdInput)
|
||||||
result.outputHandle = TFileHandle(si.hStdOutput)
|
result.outHandle = TFileHandle(si.hStdOutput)
|
||||||
result.errorHandle = TFileHandle(si.hStdError)
|
result.errHandle = TFileHandle(si.hStdError)
|
||||||
|
|
||||||
var cmdl: cstring
|
var cmdl: cstring
|
||||||
when false: # poUseShell in options:
|
when false: # poUseShell in options:
|
||||||
|
|
@ -389,9 +413,9 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
proc close(p: PProcess) =
|
proc close(p: PProcess) =
|
||||||
when false:
|
when false:
|
||||||
# somehow this does not work on Windows:
|
# somehow this does not work on Windows:
|
||||||
discard CloseHandle(p.inputHandle)
|
discard CloseHandle(p.inHandle)
|
||||||
discard CloseHandle(p.outputHandle)
|
discard CloseHandle(p.outHandle)
|
||||||
discard CloseHandle(p.errorHandle)
|
discard CloseHandle(p.errHandle)
|
||||||
discard CloseHandle(p.FProcessHandle)
|
discard CloseHandle(p.FProcessHandle)
|
||||||
|
|
||||||
proc suspend(p: PProcess) =
|
proc suspend(p: PProcess) =
|
||||||
|
|
@ -425,13 +449,13 @@ when defined(Windows) and not defined(useNimRtl):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
proc inputStream(p: PProcess): PStream =
|
proc inputStream(p: PProcess): PStream =
|
||||||
result = newFileHandleStream(p.inputHandle)
|
result = newFileHandleStream(p.inHandle)
|
||||||
|
|
||||||
proc outputStream(p: PProcess): PStream =
|
proc outputStream(p: PProcess): PStream =
|
||||||
result = newFileHandleStream(p.outputHandle)
|
result = newFileHandleStream(p.outHandle)
|
||||||
|
|
||||||
proc errorStream(p: PProcess): PStream =
|
proc errorStream(p: PProcess): PStream =
|
||||||
result = newFileHandleStream(p.errorHandle)
|
result = newFileHandleStream(p.errHandle)
|
||||||
|
|
||||||
proc execCmd(command: string): int =
|
proc execCmd(command: string): int =
|
||||||
var
|
var
|
||||||
|
|
@ -626,20 +650,20 @@ elif not defined(useNimRtl):
|
||||||
|
|
||||||
if poParentStreams in options:
|
if poParentStreams in options:
|
||||||
# does not make much sense, but better than nothing:
|
# does not make much sense, but better than nothing:
|
||||||
result.inputHandle = 0
|
result.inHandle = 0
|
||||||
result.outputHandle = 1
|
result.outHandle = 1
|
||||||
if poStdErrToStdOut in options:
|
if poStdErrToStdOut in options:
|
||||||
result.errorHandle = result.outputHandle
|
result.errHandle = result.outHandle
|
||||||
else:
|
else:
|
||||||
result.errorHandle = 2
|
result.errHandle = 2
|
||||||
else:
|
else:
|
||||||
result.inputHandle = p_stdin[writeIdx]
|
result.inHandle = p_stdin[writeIdx]
|
||||||
result.outputHandle = p_stdout[readIdx]
|
result.outHandle = p_stdout[readIdx]
|
||||||
if poStdErrToStdOut in options:
|
if poStdErrToStdOut in options:
|
||||||
result.errorHandle = result.outputHandle
|
result.errHandle = result.outHandle
|
||||||
discard close(p_stderr[readIdx])
|
discard close(p_stderr[readIdx])
|
||||||
else:
|
else:
|
||||||
result.errorHandle = p_stderr[readIdx]
|
result.errHandle = p_stderr[readIdx]
|
||||||
discard close(p_stderr[writeIdx])
|
discard close(p_stderr[writeIdx])
|
||||||
discard close(p_stdin[readIdx])
|
discard close(p_stdin[readIdx])
|
||||||
discard close(p_stdout[writeIdx])
|
discard close(p_stdout[writeIdx])
|
||||||
|
|
@ -648,9 +672,9 @@ elif not defined(useNimRtl):
|
||||||
if p.inStream != nil: close(p.inStream)
|
if p.inStream != nil: close(p.inStream)
|
||||||
if p.outStream != nil: close(p.outStream)
|
if p.outStream != nil: close(p.outStream)
|
||||||
if p.errStream != nil: close(p.errStream)
|
if p.errStream != nil: close(p.errStream)
|
||||||
discard close(p.inputHandle)
|
discard close(p.inHandle)
|
||||||
discard close(p.outputHandle)
|
discard close(p.outHandle)
|
||||||
discard close(p.errorHandle)
|
discard close(p.errHandle)
|
||||||
|
|
||||||
proc suspend(p: PProcess) =
|
proc suspend(p: PProcess) =
|
||||||
if kill(-p.id, SIGSTOP) != 0'i32: OSError(OSLastError())
|
if kill(-p.id, SIGSTOP) != 0'i32: OSError(OSLastError())
|
||||||
|
|
@ -696,17 +720,17 @@ elif not defined(useNimRtl):
|
||||||
|
|
||||||
proc inputStream(p: PProcess): PStream =
|
proc inputStream(p: PProcess): PStream =
|
||||||
if p.inStream == nil:
|
if p.inStream == nil:
|
||||||
createStream(p.inStream, p.inputHandle, fmWrite)
|
createStream(p.inStream, p.inHandle, fmWrite)
|
||||||
return p.inStream
|
return p.inStream
|
||||||
|
|
||||||
proc outputStream(p: PProcess): PStream =
|
proc outputStream(p: PProcess): PStream =
|
||||||
if p.outStream == nil:
|
if p.outStream == nil:
|
||||||
createStream(p.outStream, p.outputHandle, fmRead)
|
createStream(p.outStream, p.outHandle, fmRead)
|
||||||
return p.outStream
|
return p.outStream
|
||||||
|
|
||||||
proc errorStream(p: PProcess): PStream =
|
proc errorStream(p: PProcess): PStream =
|
||||||
if p.errStream == nil:
|
if p.errStream == nil:
|
||||||
createStream(p.errStream, p.errorHandle, fmRead)
|
createStream(p.errStream, p.errHandle, fmRead)
|
||||||
return p.errStream
|
return p.errStream
|
||||||
|
|
||||||
proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
|
proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
|
||||||
|
|
@ -717,14 +741,14 @@ elif not defined(useNimRtl):
|
||||||
proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) =
|
proc createFdSet(fd: var TFdSet, s: seq[PProcess], m: var int) =
|
||||||
FD_ZERO(fd)
|
FD_ZERO(fd)
|
||||||
for i in items(s):
|
for i in items(s):
|
||||||
m = max(m, int(i.outputHandle))
|
m = max(m, int(i.outHandle))
|
||||||
FD_SET(cint(i.outputHandle), fd)
|
FD_SET(cint(i.outHandle), fd)
|
||||||
|
|
||||||
proc pruneProcessSet(s: var seq[PProcess], fd: var TFdSet) =
|
proc pruneProcessSet(s: var seq[PProcess], fd: var TFdSet) =
|
||||||
var i = 0
|
var i = 0
|
||||||
var L = s.len
|
var L = s.len
|
||||||
while i < L:
|
while i < L:
|
||||||
if FD_ISSET(cint(s[i].outputHandle), fd) != 0'i32:
|
if FD_ISSET(cint(s[i].outHandle), fd) != 0'i32:
|
||||||
s[i] = s[L-1]
|
s[i] = s[L-1]
|
||||||
dec(L)
|
dec(L)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue