Re: [Vala] FileStream not closed after going out of scope



try something like this (it is only a demonstration, not working code!)

key to solve problem you've encountered are

          io_stdout = null;
          io_stderr = null;

it unrefs io channel, and releases descriptors




        private IOChannel     io_stderr;
        private IOChannel     io_stdout;
        private uint          io_stderr_watch_id;
        private uint          io_stdout_watch_id;
        private Pid           child_pid;
        private uint          child_watch_id = 0;

        private void run() {
          int child_stdout;
          int child_stderr;

          Process.spawn_async_with_pipes(null, { command }, null,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, null, out
child_pid, null, out child_stdout, out child_stderr);

          io_stdout = new IOChannel.unix_new(child_stdout);
          io_stderr = new IOChannel.unix_new(child_stderr);

          io_stdout_watch_id = io_stdout.add_watch(IOCondition.IN,
on_stdout_read);
          io_stderr_watch_id = io_stderr.add_watch(IOCondition.IN,
on_stderr_read);

          child_watch_id = ChildWatch.add(child_pid, on_child_exits);
        }

        private void on_child_exits(Pid pid, int status) {
          Process.close_pid(pid);

          GLib.Source.remove(io_stdout_watch_id);
          GLib.Source.remove(io_stderr_watch_id);

          try {
            io_stdout.shutdown(true);
          } catch(IOChannelError e) {
            warning(@"Error \"$(e.message)\" during shutting down
stdout pipe to the child process");
          }

          try {
            io_stderr.shutdown(true);
          } catch(IOChannelError e) {
            warning(@"Error \"$(e.message)\" during shutting down
stderr pipe to the child process");
          }

          io_stdout = null;
          io_stderr = null;

          cancel_child_watch();
        }


        private string? on_read(IOChannel source)   {
          string line;
          try {
            IOStatus ret = source.read_line(out line, null, null);

            switch(ret) {
              case IOStatus.ERROR:
                warning("Read error");
                kill();
                return null;

              case IOStatus.EOF:
                message("End of File");
                return null;

            }
          } catch(IOChannelError e) {
            warning(@"I/O error: $(e.message)");
            kill();
            return null;


          } catch(ConvertError e) {
            warning(@"Convert error: $(e.message)");
            return null;
          }

          return line;
        }


        private bool on_stderr_read(IOChannel source, IOCondition condition) {
          var line = on_read(source);
          if(line != null) {
            do_something(line);
          }

          return true;
        }

        private bool on_stdout_read(IOChannel source, IOCondition condition) {
          var line = on_read(source);
          if(line != null) {
            do_something(line);
          }

          return true;
        }


2012/9/24 tomw <tomw ubilix com>:
ok, here's a bit more meat. Hopefully this help to tackle the issue:

currently I'm using Vala 0.17.6. Obviously some files are left open as
the open file count is increasing (checking with lsof | wc -l ) until I
get the span error:

Error spawning Uptime process - Failed to create pipe for communicating
with child process (Too many open files)

thanks,



/* pipetest.vala
*  valac --pkg gio-2.0 --pkg posix pipetest.vala
*/

using GLib;


public class Pipetest.Main : Object {
        public MainLoop main_loop;
        public int counter = 0;


        public  Main () {
                main_loop = new GLib.MainLoop (null, false);
        }



        public void run () {
                Timeout.add_seconds (1, get_uptime);
                }

        public bool get_uptime () {
                string uptime = "";
                int [] pipefd = {0, 0};


                if (Posix.pipe(pipefd) < 0) {
                        debug ("Error - unable to open pipe");
                }

                Posix.close(pipefd[1]); //closing the write end of pipe
                try {
                        string[] runme = {"/usr/bin/uptime"};
                        int input;
                        int output;
                        int error;
                        Pid child_pid;
                        bool res = Process.spawn_async_with_pipes (null,
                                                                   runme,
                                                                   null,
                                                                   SpawnFlags.DO_NOT_REAP_CHILD,
                                                                   null,
                                                                   out child_pid,
                                                                   out input,
                                                                   out pipefd[0],
                                                                   out error );

                        var filestream = FileStream.fdopen (pipefd[0], "r");
                        uptime = filestream.read_line ();
                        if (res) {
                                int child_status = 0;
                                int ret_waitpid = Posix.waitpid (child_pid, out child_status, 0);
                                if (ret_waitpid < 0 ) {
                                        debug ("Waitpid returned error code : %d", ret_waitpid);
                                }

                        Posix.close (pipefd[0]);
                        Process.close_pid (child_pid);

                        }
                } catch (SpawnError e) {
                        debug ("Error spawning Uptime process - %s", e.message);
                }

                debug ("%d : Uptime : %s", counter, uptime);
                counter++;

                return true;
        }


        static int main (string[] args) {
                var main = new Main ();
                main.run ();
                main.main_loop.run ();
                return 0;
        }

}

--
tomw <tomw ubilix com>

_______________________________________________
vala-list mailing list
vala-list gnome org
https://mail.gnome.org/mailman/listinfo/vala-list



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]