Spawn.vala
[gitlive] / Spawn.vala
index 40ba172..1601af1 100644 (file)
@@ -8,7 +8,7 @@ using Gtk;
 
 
 ///using Gee; // for array list?
-
+/*
 static int main (string[] args) {
     // A reference to our file
     
@@ -33,7 +33,7 @@ static int main (string[] args) {
     return 0;
 
 }
-
+*/
 //var Gio      = imports.gi.Gio;
 //var GLib      = imports.gi.GLib;
 
@@ -85,7 +85,7 @@ public class  SpawnConfig {
         this.env = env;
          
         async = false;
-        exceptions = false;
+        exceptions = true;
         debug = false;
         
         output = null;
@@ -93,16 +93,8 @@ public class  SpawnConfig {
         input = null;
         
     }
-    
-    public void setOptions(
-            bool async,
-            bool exceptions,
-            bool debug
-        ) {
-        this.async = async;
-        this.exceptions = exceptions;
-        this.debug = debug;
-    }
+
     public void setHandlers(
             SpawnOutput? output,
             SpawnErr? stderr,
@@ -153,7 +145,8 @@ public class Spawn : Object
        
      
         this.cfg = cfg;
-     
+        this.output = "";
+        this.stderr = "";
     
         this.cfg.cwd =  this.cfg.cwd.length  < 1 ? GLib.Environment.get_home_dir() : this.cfg.cwd;
         if (this.cfg.args.length < 0) {
@@ -169,11 +162,11 @@ public class Spawn : Object
     /**
      * @property output {String} resulting output
      */
-    string output  = "";
+    public string output;
     /**
      * @property stderr {String} resulting output from stderr
      */
-    string stderr  = "";
+    public string stderr;
      /**
      * @property result {Number} execution result.
      */
@@ -236,7 +229,7 @@ public class Spawn : Object
                 out this.pid,
                 out standard_input,
                 out standard_output,
-                       out standard_error);
+                           out standard_error);
 
                // stdout:
        
@@ -247,7 +240,26 @@ public class Spawn : Object
             
             stdout.printf("PID: %d" ,this.pid);
         }
-         
+        
+        this.ref(); // additional ref - cleared on tidyup...
+        
+        this.in_ch = new GLib.IOChannel.unix_new(standard_input);
+        this.out_ch = new GLib.IOChannel.unix_new(standard_output);
+        this.err_ch = new GLib.IOChannel.unix_new(standard_error);
+        
+        // make everything non-blocking!
+        
+        
+            
+        // using NONBLOCKING only works if io_add_watch
+          //returns true/false in right conditions
+          this.in_ch.set_flags (GLib.IOFlags.NONBLOCK);
+          this.out_ch.set_flags (GLib.IOFlags.NONBLOCK);
+          this.err_ch.set_flags (GLib.IOFlags.NONBLOCK);
+                   
+      
+
         ChildWatch.add (this.pid, (w_pid, result) => {
            
             this.result = result;
@@ -275,32 +287,18 @@ public class Spawn : Object
                          
         
         
-        this.in_ch = new GLib.IOChannel.unix_new(standard_input);
-        this.out_ch = new GLib.IOChannel.unix_new(standard_output);
-        this.err_ch = new GLib.IOChannel.unix_new(standard_error);
-        
-        // make everything non-blocking!
-        
-        
-            
-                  // using NONBLOCKING only works if io_add_watch
-          //returns true/false in right conditions
-          this.in_ch.set_flags (GLib.IOFlags.NONBLOCK);
-          this.out_ch.set_flags (GLib.IOFlags.NONBLOCK);
-          this.err_ch.set_flags (GLib.IOFlags.NONBLOCK);
-                   
-      
+       
             
             // add handlers for output and stderr.
         
         this.out_src = (int) this.out_ch.add_watch (
             IOCondition.OUT | IOCondition.IN  | IOCondition.PRI |  IOCondition.HUP |  IOCondition.ERR  ,
             (channel, condition) => {
-               return this.read(this.out_ch);
+                return this.out_ch != null ? this.read(this.out_ch) : true;
             }
         );
         this.err_src = (int) this.err_ch.add_watch (
-           IOCondition.OUT | IOCondition.IN  | IOCondition.PRI |  IOCondition.HUP |  IOCondition.ERR  ,
+                IOCondition.OUT | IOCondition.IN  | IOCondition.PRI |  IOCondition.HUP |  IOCondition.ERR  ,
             (channel, condition) => {
                return this.read(this.err_ch);
             }
@@ -338,18 +336,21 @@ public class Spawn : Object
         // start mainloop if not async..
         
         if (this.pid > -1) {
-            if (this.cfg.debug) {
-                print("starting main loop");
-            }
+             print("starting main loop");
+             //if (this.cfg.debug) {
+             //  
+             // }
                this.ctx = new MainLoop ();
             this.ctx.run(); // wait fore exit?
             
-            //print("main_loop done!");
+            print("main_loop done!");
         } else {
             this.tidyup(); // tidyup get's called in main loop. 
         }
         
         if (this.cfg.exceptions && this.result != 0) {
+           
+            throw new SpawnError.EXECUTE_ERROR(this.stderr);
             //this.toString = function() { return this.stderr; };
             ///throw new Exception this; // we throw self...
         }
@@ -364,6 +365,7 @@ public class Spawn : Object
 
     private void tidyup()
     {
+        this.unref();
         if (this.pid > -1) {
             Process.close_pid(this.pid); // hopefully kills it..
             this.pid = -1;
@@ -413,6 +415,7 @@ public class Spawn : Object
         return str.length;
         
     }
     
     /**
      * read from pipe and call appropriate listerner and add to output or stderr string.
@@ -423,7 +426,7 @@ public class Spawn : Object
     {
         string prop = (ch == this.out_ch) ? "output" : "stderr";
        // print("prop: " + prop);
-
+        
         
         //print(JSON.stringify(ch, null,4));
         while (true) {
@@ -431,11 +434,23 @@ public class Spawn : Object
             size_t term_pos;
             size_t len;
             IOStatus status;
+            
+            if (this.pid < 0) {
+                return false; // spawn complete + closed... can't read any more.
+            }
+            
             try {
+                               var cond = ch.get_buffer_condition();
+                               if ((cond & GLib.IOCondition.ERR) > 0) {
+                                       return false;
+                               }
+                               if ((cond & GLib.IOCondition.IN) < 1) {
+                                       return false;
+                               }
                 status = ch.read_line( out buffer,  out len,  out term_pos );
             } catch (Error e) {
                 //FIXme
-                break; // ??
+               return false;
                 
             }
 
@@ -451,14 +466,16 @@ public class Spawn : Object
                     //}
                     if (ch == this.out_ch) {
                         this.output += buffer;
-                        this.cfg.output(  buffer);                  
+                        if (this.cfg.output != null) {
+                                this.cfg.output(  buffer);                  
+                        }
                     } else {
                         this.stderr += buffer;
                     }
                     //_this[prop] += x.str_return;
-                    if (this.cfg.debug) {
+                    //if (this.cfg.debug) {
                         stdout.printf("%s : %s", prop , buffer);
-                    }
+                    //}
                     if (this.cfg.async) {
                          
                         if ( Gtk.events_pending()) {