Skip to content

IO Channels Sample ​

Vala port of the pipe example described in this Linux Journal article. It uses GLib.IOChannel with a GLib.MainLoop so reads and writes on a pipe are driven by event sources. The program runs until you stop it (for example with Ctrl+C). It adapts the archived Vala IoChannelsSample page on the GNOME Wiki.

Program ​

Save as giochanneltest.vala:

vala
public class PipeTalker : Object {

    // reading callback
    private bool gio_in (IOChannel gio, IOCondition condition) {
        IOStatus ret;
        string msg;
        size_t len;

        if ((condition & IOCondition.HUP) == IOCondition.HUP) {
            print ("Read end of pipe died!\n");
        }

        try {
            ret = gio.read_line (out msg, out len, null);
        } catch (IOChannelError e) {
            print ("Error reading: %s\n", e.message);
            return false;
        } catch (ConvertError e) {
            print ("Error reading: %s\n", e.message);
            return false;
        }

        print ("Read %u bytes: %s\n", (uint) len, msg);

        return true;
    }

    // writing callback
    private bool gio_out (IOChannel gio, IOCondition condition) {
        string msg = "The price of greatness is responsibility.\n";
        IOStatus ret;
        size_t len;

        if ((condition & IOCondition.HUP) == IOCondition.HUP) {
            print ("Write end of pipe died!\n");
        }

        try {
            ret = gio.write_chars ((char[]) msg, out len);
        } catch (IOChannelError e) {
            print ("Error writing: %s\n", e.message);
            return false;
        } catch (ConvertError e) {
            print ("Error writing: %s\n", e.message);
            return false;
        }

        print ("Wrote %u bytes.\n", (uint) len);

        return true;
    }

    public void init_channels () {
        IOChannel io_read, io_write;
        int[] fd = new int[2];
        int ret;

        ret = Posix.pipe (fd);
        if (ret == -1) {
            print ("Creating pipe failed: %s\n", GLib.strerror (Posix.errno));
            return;
        }

        io_read = new IOChannel.unix_new (fd[0]);
        io_write = new IOChannel.unix_new (fd[1]);

        if (io_read == null || io_write == null) {
            print ("Cannot create new IOChannel!\n");
            return;
        }

        if (io_read.add_watch (IOCondition.IN | IOCondition.HUP, gio_in) == 0) {
            print ("Cannot add watch on IOChannel!\n");
            return;
        }

        if (io_write.add_watch (IOCondition.OUT | IOCondition.HUP, gio_out) == 0) {
            print ("Cannot add watch on IOChannel!\n");
            return;
        }
    }

    public static int main () {
        var loop = new MainLoop (null, false);
        var pt = new PipeTalker ();
        pt.init_channels ();
        loop.run ();
        return 0;
    }
}

Compile and run ​

shell
valac --pkg posix giochanneltest.vala
./giochanneltest