A PIPE device is specified with a "PIPE" value for mnemonicspace on an OPEN command.
![]() | Note |
---|---|
GT.M ignores the mnemonicspace specification on an OPEN of a previously OPEN device and leaves the existing device with its original characteristics. |
set p="Printer" open p:(command="lpr":writeonly)::"PIPE"
set p="MyProcs" open p:(command="ps -ef|grep $USER":readonly)::"PIPE"
![]() | Note |
---|---|
Flags to the ps command vary for different UNIX platforms. |
set p="Convert" open p:(shell="/bin/csh":command="iconv -f ISO_8859-1 -t WINDOWS-1252")::"PIPE"
set p="Files" set e="Errors" open p:(command="find /var/log -type d -print":readonly:stderr=e)::"PIPE"
The following characteristics of PIPE may be helpful in using them effectively.
Operation |
Result |
$DEVICE |
$ZA |
$TEST |
X |
$ZEOF |
---|---|---|---|---|---|---|
READ X:n |
Normal Termination |
0 |
0 |
1 |
Data Read |
0 |
READ X:n |
Timeout with no data read |
0 |
0 |
0 |
empty string |
0 |
READ X:n |
Timeout with partial data read |
0 |
0 |
0 |
Partial data |
0 |
READ X:n |
End of File |
1,Device detected EOF |
9 |
1 |
empty string |
1 |
READ X:0 |
Normal Termination |
0 |
0 |
1 |
Data Read |
0 |
READ X:0 |
No data available |
0 |
0 |
0 |
empty string |
0 |
READ X:0 |
Timeout with partial data read |
0 |
0 |
0 |
Partial data |
0 |
READ X:0 |
End of File |
1,Device detected EOF |
9 |
1 |
empty string |
1 |
READ X |
Error |
1,<error signature> |
9 |
n/c |
empty string |
0 |
The following examples show the use of deviceparameters and status variables with PIPE devices.
pipe1; set p1="test1" open p1:(shell="/bin/sh":comm="cat")::"PIPE" for i=1:1:10 do . use p1 . write i,":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ",! . read x . use $P . write x,! close p1 quit
pipe3; set p1="test1" open p1:(shell="/bin/sh":command="tr -d e")::"PIPE" for i=1:1:1000 do . use p1 . write i,":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ",! . read x:0 . if '+$device use $principal write x,! use p1 write /EOF for read x quit:$zeof use $principal write x,! use p1 close p1 quit
pipe4; set a="test" open a:(command="nestin":independent)::"PIPE" use a set key=$KEY write "Show nestin still running after CLOSE of a",! write "The parent process of 1 shows the parent shell has exited after CLOSE of a" read line1,line2 use $principal write !,line1,!,line2,!,! set k="ps -ef | grep -v grep | grep -v sh | grep -w '"_key_"' | awk '{print $2}'" set b="getpid" open b:(command=k:readonly)::"PIPE" use b read pid close a close b set k2="ps -ef | grep -v grep | grep -v sh | grep -w '"_pid_"'" set c="psout" open c:(command=k2:writeonly)::"PIPE" close c quit
![]() | Note |
---|---|
"nestin.c" is a program which reads from standard input and writes to standard output until it see and EOF. It then loops for 300 1sec sleeps doing nothing. The purpose of using independent is as a server process which continues until it receives some other signal for termination. |
GTM>kill ^a GTM>zprint ^indepserver indepserver; read x write "received = ",x,! set ^quit=0 for do quit:^quit . if $data(^a) write "^a = ",^a,! . Hang 5 GTM>set a="test" GTM>open a:(command="mumps -run ^indepserver>indout":independent)::"pipe" GTM>use a GTM>write "instructions",! GTM>close a GTM>zsystem "cat indout" received = instructions GTM>set ^a=1 GTM>zsystem "cat indout" received = instructions ^a = 1 ^a = 1 ^a = 1 GTM>s ^quit=1 GTM>zsystem "cat indout" received = instructions ^a = 1 ^a = 1 ^a = 1 ^a = 1 GTM>
This is a simple example using a mumps process as a server.
pipe5; set p1="test1" set a=0 open p1:(shell="/bin/sh":command="cat":exception="goto cont1")::"PIPE" set c=":abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz" for i=1:1:10000 do . use p1 . write i_c,! . use $principal write i,! use p1 write /EOF for read x quit:$zeof use $principal write x,! use p1 close p1 quit cont1 if $zeof quit if a=0 set a=i/2 set z=$za ; use $device to make sure ztrap is caused by blocked write to pipe set d=$device if "1,Resource temporarily unavailable"=d DO . use $p . write "pipe full, i= ",i," $ZA = ",z,! . set i=i-1 . use p1 . for j=1:1:a read x use $principal write j,"-",x,! use p1 quit
; Example program that starts another program in a pipe and traps the errors. The called ; programs intentionally induce errors pipexample set $etrap="do readfrompipe(.pipe,.piperr) use $p zwrite $zstatus zhalt 99" set pipe="pipe" set piperr="piperr" set writesize=1024 set cmd=$piece($zcmdline," ") set:'$length(cmd) cmd="induceEPIPE" open pipe:(shell="/bin/bash":command="$gtm_dist/mumps -run "_cmd_"^pipexample":stderr=piperr)::"pipe" zshow "D":devicelist write "The active device is ",devicelist("D",2),! use pipe for i=1:1:1024 write $tr($justify(i,writesize)," ","X"),! close pipe quit ; Same as above, but without defining the PIPE's standard error nostderr set $etrap="do readfrompipe(.pipe) use $p zshow ""*"" zhalt 99" set pipe="pipe" set writesize=1024 set cmd=$piece($zcmdline," ",2) set:'$length(cmd) cmd="induceEAGAIN" open pipe:(shell="/bin/bash":command="$gtm_dist/mumps -run "_cmd_"^pipexample")::"pipe" zshow "D":devicelist write "The active device is ",devicelist("D",2),! write !,! use pipe for i=1:1:1024 write $tr($justify(i,writesize)," ","X"),! close pipe quit ; This routine intentionally delays reading from the pipe to induce an EAGAIN induceEAGAIN set $etrap="use $p zwrite $zstatus zhalt 99" set hangtime=+$zcmdline set:'hangtime hangtime=5 set add=1 for i=1:1:1024 read x(i) quit:$zeof do . set delay(i)=1/(add+$random(hangtime)) . hang delay(i) . set:i=30 add=10 halt ; This routine intentionally induces an EPIPE by immediately sending a SIGTERM to itself causing ; a FORCEDHALT error which goes to STDERR. Subsequently, a random DIVZERO error occurs, but this ; error goes to STDOUT since it is not a fatal error induceEPIPE set $etrap="use $p zwrite $zstatus zhalt 99" set divzero=150373210 ; DIVZERO goes to stdout write "My PID is ",$job,! zsystem:'$zcmdline "kill -15 "_$job ; FORCEDHALT error goes to stderr for i=1:1 read x(i) quit:$zeof zmessage:'$random(1000) divzero halt ; Read the contents of the pipe on failure. Messages from the programs inside the pipe aid ; in undestanding the underlying problem(s) readfrompipe(pipe,piperr) new i new $etrap set $etrap="set x=$zjobexam() zhalt 88" use pipe for i=1:1 read pipe(i):0 quit:'$test!$zeof zkill pipe(i) do:$data(piperr) . use piperr . for i=1:1 read piperr(i):0 quit:'$test!$zeof . zkill piperr(i) close pipe use $p for i=1:1 quit:'$data(pipe(i)) write ?4,"stdout:",pipe(i),! for i=1:1 quit:'$data(piperr(i)) write ?4,"stderr:",piperr(i),! quit ; Example of trapping an error and retrying the operation as necessary. Error conditions ; used are EPIPE, aka "Broken pipe" or ENO32, and EAGAIN, aka ENO11. retry set $etrap="use $p zshow ""*"" zhalt 99" set pipe="pipe" set piperr="piperr" set writesize=1024 set cmd=$piece($zcmdline," ") set:'$length(cmd) cmd="induceEPIPE" for try=0:1 do quit:$get(readcomplete,0) . new $etrap set $etrap="goto retryEPIPE" . open pipe:(shell="/bin/bash":command="$gtm_dist/mumps -run "_cmd_"^pipexample "_try:stderr=piperr)::"pipe" . zshow "D":devicelist write "Try ",try,$char(9),devicelist("D",2),! . use pipe . for i=1:1:1024 do . . new $etrap set $etrap="goto retryEAGAIN^pipexample" . . write $tr($justify(i,writesize)," ","X"),! . set readcomplete=1 close pipe use $p write ?4,"Writes completed",! quit retryEPIPE quit:$zstatus'["ENO32" use $p write "...Caught on try ",try,", write ",i,"... ",$zstatus,! set $ecode="" do readfrompipe(.pipe,.piperr) quit retryEAGAIN quit:$zstatus'["ENO11" use $p write "...Failed to perform non-blocked writes... Retrying write # ",$increment(i,-1),! set $ecode="" hang 1+$random(5) use pipe quit
sh> mumps -run pipexample induceEAGAIN The active device is pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEAGAIN^pipexample" STDERR="piperr" $ZSTATUS="11,pipexample+9^pipexample,%SYSTEM-E-ENO11, Resource temporarily unavailable" sh> mumps -run retry^pipexample induceEAGAIN Try 0 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEAGAIN^pipexample 0" STDERR="piperr" ...Failed to perform non-blocked writes... Retrying write # 54 ...Failed to perform non-blocked writes... Retrying write # 63 ...Failed to perform non-blocked writes... Retrying write # 69 ...Failed to perform non-blocked writes... Retrying write # 78 Writes completed
sh> mumps -run pipexample induceEPIPE The active device is pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample" STDERR="piperr" stdout:My PID is 12808 stderr:%GTM-F-FORCEDHALT, Image HALTed by MUPIP STOP $ZSTATUS="32,pipexample+9^pipexample,%SYSTEM-E-ENO32, Broken pipe" sh> mumps -run retry^pipexample induceEPIPE Try 0 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample 0" STDERR="piperr" ...Caught on try 0, write 49... 32,retry+13^pipexample,%SYSTEM-E-ENO32, Broken pipe stdout:My PID is 16252 stderr:%GTM-F-FORCEDHALT, Image HALTed by MUPIP STOP Try 1 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample 1" STDERR="piperr" ...Caught on try 1, write 697... 32,retry+13^pipexample,%SYSTEM-E-ENO32, Broken pipe stdout:My PID is 16403 stdout:$ZSTATUS="150373210,induceEPIPE+5^pipexample,%GTM-E-DIVZERO, Attempt to divide by zero" Try 2 pipe OPEN PIPE SHELL="/bin/bash" COMMAND="$gtm_dist/mumps -run induceEPIPE^pipexample 2" STDERR="piperr" Writes completed
The following table summarizes the PIPE format deviceparameters.
DEVICE PARAMETER |
CMD |
DESCRIPTION |
---|---|---|
[NO]FIXED |
O |
Controls whether records have fixed length |
RECORDSIZE=intexpr |
O |
Specifies the maximum record size. |
VARIABLE |
O |
Controls whether records have variable length. |
[Z]WIDTH=intexpr |
U |
Sets the device's logical record size and enables WRAP. |
[Z][NO]WRAP |
O/U |
Controls the handling of records longer than the device width. |
The following table summarizes PIPE access deviceparamters.
COMMAND=string |
o |
Specifies the command string to execut in a created process for the PIPE device. GT.M uses the default searching mechanism of the UNIX shell for creating the process and initiating its command(s). |
SHELL=string |
o |
Specifies the path to a shell to be used instead of the default shell |
STDERR=string |
o |
Specifies a device handle for a return pipe to which the created process writes any standard error output. The GT.M process can USE, READ, and CLOSE it, but cannot WRITE to it. When the GT.M process CLOSEs the PIPE device, the PIPE device CLOSEs STDERR, if still OPEN. |
WRITEONLY |
o |
Specifies that the GT.M process may only WRITE to the created process via the PIPE device. |
READONLY |
o |
Specifies that the GT.M process may only READ from the created process via the PIPE device. Output from both the standard output and the standard error output of the created process is available unless STDERR is specified. |
PARSE |
o |
Specifies that GT.M parse the COMMAND and issue an OPEN exception for any invalid command. |
INDEPENDENT |
o |
Specifies that the created process continues to execute after the PIPE device is CLOSEd. |