[gnome-builder] doc: add docs for subprocesses, supervisors, and PTYs



commit ec0388ddb81fe2148f82c988b318a78a6424a658
Author: Christian Hergert <chergert redhat com>
Date:   Wed Mar 15 13:47:59 2017 -0700

    doc: add docs for subprocesses, supervisors, and PTYs

 doc/plugins/processes/subprocesses.rst |  132 ++++++++++++++++++++++++++++++++
 1 files changed, 132 insertions(+), 0 deletions(-)
---
diff --git a/doc/plugins/processes/subprocesses.rst b/doc/plugins/processes/subprocesses.rst
index 0976d0c..f003400 100644
--- a/doc/plugins/processes/subprocesses.rst
+++ b/doc/plugins/processes/subprocesses.rst
@@ -1,3 +1,135 @@
 #################################
 Subprocesses and Psuedo Terminals
 #################################
+
+
+Creating Subprocesses
+=====================
+
+Builder provides a powerful abstraction for creating subprocesses.
+``Ide.Subprocess`` allows you to setup and modify how a processes should be launched without the burden of 
how to launch the subprocess.
+This means that Builder can use different strategies based on the host system, subprocess requirements, and 
plugins that may need to modify the program arguments.
+
+When Builder is not running in a sandbox, it can generally execute subprocesses the normal way using fork 
and exec.
+However, if Builder is sandboxed, it may need to run the subprocess on the host rather than inside the 
sandbox.
+To ensure your subprocess is run on the host, use ``Ide.Subprocess.set_run_on_host()``.
+
+.. note:: You can only run programs on the host that are already installed.
+          Use ``which program-name`` to determine if the process is available on the host.
+
+If you are integrating an external tool, such as Valgrind, you might need to inject arguments into the 
argument array.
+For the Valgrind case, ``Ide.Subprocess.prepend_argv()`` of ``"valgrind"`` would be appropriate.
+
+Some runtime plugins may need to modify the argument array even further.
+For example, the Flatpak plugin will require that all commands start with ``flatpak build ...`` so that the 
commands are never run on the host system, but instead inside the runtime.
+Plugins that require this should inject their additional arguments from the 
``Ide.SubprocessLauncher.spawn()`` virtual-method so that plugins do not get confused about the placement of 
arguments.
+
+
+.. code-block:: py
+
+   from gi.repository import GLib
+   from gi.repository import Ide
+
+   # You may want access to stdin/stdout/stderr. If so, ensure you specify
+   # the appropriate Gio.SubprocessFlags for your subprocess.
+   launcher = Ide.SubprocessLauncher.new(Gio.SubprocessFlags.STDOUT_PIPE |
+                                         Gio.SubprocessFlags.STDERR_PIPE |
+                                         Gio.SubprocessFlags.STDIN_PIPE)
+
+   # If you need to specify where to launch the process. The default
+   # is the home directory.
+   launcher.set_cwd(os.path.join(GLib.get_home_dir(), 'Projects'))
+
+   # Push some arguments onto argv
+   launcher.push_argv('which')
+   launcher.push_argv('ls')
+
+   # Set some environment variables
+   launcher.setenv('LANG', 'C', True)
+
+   # Spawn the process. If you pass in a Gio.Cancellable, you can kill the
+   # subprocess by calling Gio.Cancellable.cancel().
+   subprocess = launcher.spawn(None)
+
+   # We need to wait for the child to complete. If you want to read the
+   # output of the subprocess, see Ide.Subprocess.communicate_utf8().
+   # wait_check() will ensure the return value is zero. If you do not
+   # care about the return value, just use wait().
+   try:
+       subprocess.wait_check(None)
+   except Exception as ex:
+       print(repr(ex))
+
+    # May Ide.Subprocess API have async variants. Consider using them to
+    # avoid needlessly blocking threads.
+
+
+Supervising Subprocesses
+========================
+
+There are times where you might want to respawn a process in case it exits prematurely.
+Builder provides the ``Ide.SubprocessSupervisor`` abstraction to simplify this for you.
+
+The ``Ide.SubprocessSupervisor`` has a simple API.
+Just attach your ``Ide.SubprocessLauncher`` using ``Ide.SubprocessSupervisor.set_launcher()`` and call 
``Ide.SubprocessSupervisor.start()``.
+
+If the subprocess begins flapping (exiting immediately after spawning) some delay will be added to slow 
things down.
+
+To stop the subprocess, use ``Ide.SubprocessSupervisor.stop()``.
+
+If you need access to the subprocess, you can access it either via the 
``Ide.SubprocessSupervisor.get_subprocess()`` method or by connecting to the 
``Ide.SubprocessSupervisor::spawned()`` signal.
+
+.. code-block:: py
+
+   def on_subprocess_spawned(supervisor, subprocess):
+       print("Spawned process " + subprocess.get_identifier())
+
+   launcher = create_launcher()
+
+   supervisor = Ide.SubprocessSupervisor()
+   supervisor.set_launcher(launcher)
+   supervisor.connect('spawned', on_subprocess_spawned)
+   supervisor.start()
+
+
+Psuedo Terminals
+================
+
+Psuedo terminals are tricky business.
+In general, if you need access to a PTY, use the VTE library like Builder's terminal plugin.
+For an example of how to setup the PTY, we use a flow like this.
+
+.. code-block:: c
+
+   // This code does little to no error checking.
+   // Your code should be more careful.
+
+   // First create our PTY master
+   VtePty *pty = vte_terminal_pty_new_sync (terminal,
+                                            VTE_PTY_DEFAULT | VTE_PTY_NO_LASTLOG | VTE_PTY_NO_UTMP | 
VTE_PTY_NO_WTMP,
+                                            NULL, &error);
+
+   // Now go through the PTY slave setup
+   int master_fd = vte_pty_get_fd (pty);
+   
+   assert (grantpt (master_fd) != 0);
+   assert (unlockpt (master_fd) != 0);
+
+   // Get the path to the PTY slave
+   char name[PATH_MAX];
+   assert (ptsname_r (master_fd, name, sizeof name - 1) != 0);
+   name [sizeof name - 1] = '\0';
+
+   // Open the PTY slave
+   int slave_fd = open (name, O_RDWR | O_CLOEXEC);
+
+   // Now, when spawning a process, you can set stdin/stdout/stderr to the FD
+   // of the slave. We use dup() because the callee takes ownership.
+   ide_subprocess_launcher_take_stdin_fd (launcher, dup (slave_fd));
+   ide_subprocess_launcher_take_stdout_fd (launcher, dup (slave_fd));
+   ide_subprocess_launcher_take_stderr_fd (launcher, dup (slave_fd));
+   close (slave_fd);
+
+When launching the subprocess with Builder, it will detect that ``stdin``, ``stdout``, or ``stderr`` are 
pseudo terminals and perform the proper ``ioctl()`` setup for you.
+This allows for the PTY to cross the sandbox boundary to the host, ensuring that you may have a host-based 
shell with a PTY from within the sandbox.
+


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