OSProcess.st
changeset 21208 9fbb51649256
parent 21206 aad552f2f306
child 21209 e9395c842124
--- a/OSProcess.st	Thu Dec 29 00:41:03 2016 +0100
+++ b/OSProcess.st	Thu Dec 29 20:41:04 2016 +0100
@@ -99,15 +99,14 @@
 
 !OSProcess methodsFor:'accessing'!
 
-accessor
-    ^ self
-!
-
 auxStream
     ^ auxStream
 !
 
 auxStream:something
+    "set an auxilliary input stream that will be available to the command as
+     file descriptor 3"
+
     auxStream := something.
 !
 
@@ -119,12 +118,14 @@
     "Created: / 10.11.1998 / 21:27:07 / cg"
 !
 
-command:something
-    "set the value of the instance variable 'command' (automatically generated)"
+command:aStringOrArray
+    "set the command to be executed.
+     If aStringOrArray is a String, the commandString is passed to a shell for execution
+     - see the description of 'sh -c' in your UNIX manual ('cmd.exe' in your Windows manual).
+     If aCommandString is an Array, the first element is the command to be executed,
+     and the other elements are the arguments to the command. No shell is invoked in this case."
 
-    command := something.
-
-    "Created: / 10.11.1998 / 21:27:07 / cg"
+    command := aStringOrArray.
 !
 
 directory
@@ -135,12 +136,10 @@
     "Created: / 10.11.1998 / 21:21:52 / cg"
 !
 
-directory:something
-    "set the value of the instance variable 'directory' (automatically generated)"
+directory:aString
+    "set the directory that will be set as the current directory of the command to be executed"
 
-    directory := something.
-
-    "Created: / 10.11.1998 / 21:21:52 / cg"
+    directory := aString.
 !
 
 environment
@@ -151,12 +150,10 @@
     "Created: / 10.11.1998 / 21:26:34 / cg"
 !
 
-environment:something
-    "set the value of the instance variable 'environment' (automatically generated)"
+environment:aDictionary
+    "set the environment variables of the command to be executed"
 
-    environment := something.
-
-    "Created: / 10.11.1998 / 21:27:07 / cg"
+    environment := aDictionary.
 !
 
 errorStream
@@ -167,20 +164,16 @@
     "Created: / 10.11.1998 / 21:26:34 / cg"
 !
 
-errorStream:something
-    "set the value of the instance variable 'errorStream' (automatically generated)"
+errorStream:aStream
+    "set the stream where the stderr output of the command is directed to"
 
-    errorStream := something.
-
-    "Created: / 10.11.1998 / 21:26:34 / cg"
+    errorStream := aStream.
 !
 
 exitStatus
-    "return the value of the instance variable 'exitStatus' (automatically generated)"
+    "answer the exit status of the command or nil, if the command has not yet been finished"
 
     ^ exitStatus
-
-    "Created: / 10.11.1998 / 21:24:55 / cg"
 !
 
 exitStatus:something
@@ -206,28 +199,35 @@
     "Created: / 10.11.1998 / 21:26:34 / cg"
 !
 
-inStream:something
-    "set the value of the instance variable 'inStream' (automatically generated)"
+inStream:aStream
+    "set the stream where the stdin input of the command is read from"
 
-    inStream := something.
-
-    "Created: / 10.11.1998 / 21:26:34 / cg"
+    inStream := aStream.
 !
 
 lineWise
     ^ lineWise
 !
 
-lineWise:something
-    lineWise := something.
+lineWise:aBoolean
+    "read linewise from the command's output.
+     This is a bit slower.
+     Set lineWise to true, if both error and output is sent to the same stream
+     and you don't want lines to be mangled. This is a bit slower than lineWise = false.
+
+     You may use it also when streaming to e.g. Transcript"
+
+    lineWise := aBoolean.
 !
 
 newPgrp
     ^ newPgrp
 !
 
-newPgrp:something
-    newPgrp := something.
+newPgrp:aBoolean
+    "if aBoolean is true, a new process group will be created for the command and its subprocesses"
+
+    newPgrp := aBoolean.
 !
 
 outStream
@@ -238,15 +238,15 @@
     "Created: / 10.11.1998 / 21:26:34 / cg"
 !
 
-outStream:something
-    "set the value of the instance variable 'outStream' (automatically generated)"
+outStream:aStream
+    "set the stream where the stdout output of the command is directed to"
 
-    outStream := something.
-
-    "Created: / 10.11.1998 / 21:26:34 / cg"
+    outStream := aStream.
 !
 
 pid
+    "answer the pid of the process the command is running in or nil, if the command has not yet been started."
+
     ^ pid
 !
 
@@ -258,16 +258,30 @@
     ^ showWindow
 !
 
-showWindow:something
-    showWindow := something.
+showWindow:aBooleanOrNil
+    "This parameter is ignored on Unix systems.
+
+     You can control (have to - sigh) if a window should be shown for the command or not.
+     This is the OS's H_SHOWWINDOW argument.
+     If you pass nil as showWindow-argument, the OS's default is used for the particular
+     command, which is correct most of the time: i.e. a notepad will open its window, other (non-UI)
+     executables will not.
+     However, some command-line executables show a window, even if they should not.
+     (and also, there seems to be an inconsistency between windows7 and newer windows: in newer,
+     a shell command opens a cmd-window, whereas in windows7 it did not)
+     In this case, pass an explicit false argument to suppress it."
+
+    showWindow := aBooleanOrNil.
 !
 
 terminateActionBlock
     ^ terminateActionBlock
 !
 
-terminateActionBlock:something
-    terminateActionBlock := something.
+terminateActionBlock:aBlock
+    "set the block that will be executed when the command has been finished or terminated."
+
+    terminateActionBlock := aBlock.
 ! !
 
 !OSProcess methodsFor:'initialization'!
@@ -399,6 +413,10 @@
 
 !OSProcess methodsFor:'queries'!
 
+finishedWithSuccess
+    ^ exitStatus notNil and:[exitStatus success].
+!
+
 isAlive
     "answer true, if the process is still alive"
 
@@ -425,7 +443,8 @@
     [
         ok := self startProcess.
         ok ifTrue:[
-            ok := self waitUntilFinished.
+            self waitUntilFinished.
+            ok := self finishedWithSuccess.
         ].
     ] ifCurtailed:[
         "/ we were interrupted -
@@ -501,6 +520,7 @@
         ].
         shufflerProcesses := nil.
         exitStatus := OperatingSystem osProcessStatusClass processCreationFailure.
+        finishSema signal.
         ^ false.
     ].
 
@@ -512,21 +532,27 @@
 kill
     "kill the process - the process does not get the chance to clean up"
     
-    OperatingSystem killProcess:pid.
+    pid notNil ifTrue:[
+        OperatingSystem killProcess:pid.
+    ].
 !
 
 killGroup
     "kill the processGroup - the processes do not get the chance to clean up"
 
-    OperatingSystem 
-        killProcessGroup:pid;
-        killProcess:pid.
+    pid notNil ifTrue:[
+        OperatingSystem 
+            killProcessGroup:pid;
+            killProcess:pid.
+    ].
 !
 
 terminate
     "terminate the process gracefully"
 
-    OperatingSystem terminateProcess:pid.
+    pid notNil ifTrue:[
+        OperatingSystem terminateProcess:pid.
+    ].
 !
 
 terminateGroup
@@ -534,28 +560,35 @@
      Under Windows, these is the same as terminateWithhAllChildren,
      under unix, this terminates a subset of all children"
 
-    OperatingSystem 
-        terminateProcessGroup:pid;
-        terminateProcess:pid.
+    pid notNil ifTrue:[
+        OperatingSystem 
+            terminateProcessGroup:pid;
+            terminateProcess:pid.
+    ].
 ! !
 
 !OSProcess methodsFor:'waiting'!
 
 waitUntilFinished
+    ^ self waitUntilFinishedWithTimeout:nil
+!
+
+waitUntilFinishedWithTimeout:timeout
     |processList|
 
-    finishSema waitUncounted.
+    (finishSema waitWithTimeout:timeout) isNil ifTrue:[
+        "timed out"
+        ^ nil.
+    ].
 
     "have to wait until the shufflers have finished their work"
-    shufflerProcesses notEmptyOrNil ifTrue:[
-        processList := shufflerProcesses.
+    processList := shufflerProcesses.
+    processList notEmptyOrNil ifTrue:[
         processList do:[:eachProcess | 
             eachProcess waitUntilTerminated.
         ].
         shufflerProcesses := nil.
     ].
-
-    ^ exitStatus notNil and:[exitStatus success].
 ! !
 
 !OSProcess class methodsFor:'documentation'!