/**
* @property pid {Number} pid of child process (of false if it's not running)
*/
- int pid = -1;
+ public int pid {
+ get;
+ private set;
+ default = -1;
+ }
/**
* @property in_ch {GLib.IOChannel} input io channel
*/
GLib.debug("cd %s; %s" , this.cwd , string.joinv(" ", this.args));
+ var pid = -1;
if (this.detach) {
- Process.spawn_async_with_pipes (
+ //Process.spawn_async_with_pipes (
+ Process.spawn_async (
this.cwd,
this.args,
this.env.length > 0 ? this.env : null,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
null,
- out this.pid);
- ChildWatch.add (this.pid, (pid, status) => {
- // Triggered when the child indicated by child_pid exits
- Process.close_pid (pid);
-
- });
-
- return;
+ out pid);
+
+ this.pid = pid;
+
+ ChildWatch.add (this.pid, (pid, status) => {
+
+ Process.close_pid (pid);
+
+ });
+
+ return;
}
+
+
Process.spawn_async_with_pipes (
this.cwd,
this.args,
this.env.length > 0 ? this.env : null,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD,
null,
- out this.pid,
+ out pid,
out standard_input,
out standard_output,
out standard_error);
-
+ this.pid = pid;
// stdout:
this.ctx = null;
}
this.tidyup();
- //print("DONE TIDYUP");
+ GLib.debug("DONE TIDYUP - calling complete");
this.complete(this.result, this.output, this.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 ? true : this.read(this.out_ch);
}
);
this.err_src = (int) this.err_ch.add_watch (
IOCondition.OUT | IOCondition.IN | IOCondition.PRI | IOCondition.HUP | IOCondition.ERR ,
(channel, condition) => {
- return this.read(this.err_ch);
+ return this.err_ch == null ? true : this.read(this.err_ch);
}
);
- private void tidyup()
+ public void tidyup() // or kill
{
if (this.pid > -1) {
Process.close_pid(this.pid); // hopefully kills it..
this.err_ch = null;
this.out_ch = null;
// rmeove listeners !! important otherwise we kill the CPU
- //if (this.err_src > -1 ) GLib.source_remove(this.err_src);
- //if (this.out_src > -1 ) GLib.source_remove(this.out_src);
+ if (this.err_src > -1 ) GLib.Source.remove(this.err_src);
+ if (this.out_src > -1 ) GLib.Source.remove(this.out_src);
this.err_src = -1;
this.out_src = -1;
* @arg giochannel to read from.
* @returns none
*/
- private bool read(IOChannel ch)
- {
- // string prop = (ch == this.out_ch) ? "output" : "stderr";
- // print("prop: " + prop);
+ private bool read(IOChannel ch)
+ {
+ // string prop = (ch == this.out_ch) ? "output" : "stderr";
+ // print("prop: " + prop);
-
- //print(JSON.stringify(ch, null,4));
- while (true) {
- string buffer;
- size_t term_pos;
- size_t len;
- IOStatus status;
- try {
- status = ch.read_line( out buffer, out len, out term_pos );
- } catch (Error e) {
- //FIXme
- break; // ??
-
- }
+
+ //print(JSON.stringify(ch, null,4));
+ while (true) {
+ string buffer;
+ size_t term_pos;
+ size_t len;
+ IOStatus status;
+ try {
+ status = ch.read_line( out buffer, out len, out term_pos );
+ } catch (Error e) {
+ //FIXme
+ break; // ??
+
+ }
- // print('status: ' +JSON.stringify(status));
- // print(JSON.stringify(x));
- switch(status) {
- case GLib.IOStatus.NORMAL:
+ // print('status: ' +JSON.stringify(status));
+ // print(JSON.stringify(x));
+ switch(status) {
+ case GLib.IOStatus.NORMAL:
- //write(fn, x.str);
-
- //if (this.listeners[prop]) {
- // this.listeners[prop].call(this, x.str_return);
- //}
- if (ch == this.out_ch) {
- this.output += buffer;
- this.output_line( buffer);
-
- } else {
- this.stderr += buffer;
- this.output_line( buffer);
- }
- //_this[prop] += x.str_return;
- //if (this.cfg.debug) {
- //GLib.debug("%s : %s", prop , buffer);
- //}
- if (this.is_async) {
-
- //if ( Gtk.events_pending()) {
- // Gtk.main_iteration();
- //}
-
- }
-
- //this.ctx.iteration(true);
- continue;
- case GLib.IOStatus.AGAIN:
+ //write(fn, x.str);
+
+ //if (this.listeners[prop]) {
+ // this.listeners[prop].call(this, x.str_return);
+ //}
+ if (ch == this.out_ch) {
+ this.output += buffer;
+ this.output_line( buffer);
+
+ } else {
+ this.stderr += buffer;
+ this.output_line( buffer);
+ }
+ //_this[prop] += x.str_return;
+ //if (this.cfg.debug) {
+ //GLib.debug("%s : %s", prop , buffer);
+ //}
+ if (this.is_async) {
+
+ //if ( Gtk.events_pending()) {
+ // Gtk.main_iteration();
+ //}
+
+ }
+
+ //this.ctx.iteration(true);
+ continue;
+ case GLib.IOStatus.AGAIN:
//print("Should be called again.. waiting for more data..");
- return true;
- //break;
- case GLib.IOStatus.ERROR:
- case GLib.IOStatus.EOF:
- return false;
- //break;
-
- }
- break;
- }
-
- //print("RETURNING");
- return false; // allow it to be called again..
- }
+ return true;
+ //break;
+ case GLib.IOStatus.ERROR:
+ case GLib.IOStatus.EOF:
+ return false;
+ //break;
+
+ }
+ break;
+ }
+
+ //print("RETURNING");
+ return false; // allow it to be called again..
+ }
+ public bool isZombie()
+ {
+ if (!GLib.FileUtils.test("/proc/%d".printf(this.pid), FileTest.EXISTS)) {
+ return false;
+ }
+ size_t sz;
+ string f;
+ try {
+ if (!GLib.FileUtils.get_contents("/proc/%d/stat".printf(this.pid), out f, out sz)) {
+ return false;
+ }
+ } catch(GLib.Error e) {
+ return false;
+ }
+ var bits = f.split(" ");
+ if (bits.length > 3 && bits[2] == "Z") {
+ GLib.debug("Process pid:%d is a zombie - trying waitpid", this.pid);
+ int status;
+ Posix.waitpid(this.pid, out status, 0);
+ GLib.debug("Process pid:%d is a zombie - done waitpid", this.pid);
+ return true;
+ }
+ return false;
+
+
+
+
+ }
}
/*