Skip to content

Latest commit

 

History

History
126 lines (91 loc) · 7.24 KB

File metadata and controls

126 lines (91 loc) · 7.24 KB

GPII Process Reporter

The GPII prcoesses reporter is made up of two parts:

  • a Nodejs bridge to GNOME/Linux's libgtop library to acquire information about running processes.
  • a fluid evented component that provides an interface for:
    • locating processes based on solution "commands".
    • locating processes based on solution process ids.
    • locating processes by command.
    • locating a process by its process id.
    • emitting an event when a process changes state (onStateChange).
    • emitting an event when a process switches run state (onRunStateChange).

Here is how the parts fit together, from the bottom up.

Nodejs Bridge

The code for the bridge is in the sub-folder "nodeprocesses". In essence, it consists of one JavaScript function to acquire a list of all the processes on the machine, and represent each process as a set of properties.

The first property, "command", is provided by GNOME/Linux's libgtop library and is conceptually the name of the process. Both GNOME/Linux and Mac OS X have a GUI process viewer where they display this property as the "process name". Nodejs has a "process" global object, which represents the Nodejs process itself, that uses a "title" property for the same purpose. Within bash, a simple way to find a process is to list them all using ps and then grep for the command name, e.g.:

$ ps aux | grep node

Unfortunately, the command name is not unique in the sense that more than one process can have the same name. There can be multiple "node" processes runnning simultaneously. The process id, however, is unique. Once a process has been found via its command name, thereafter, one can use its process id to reference that one process.

The full set of properties are:

  • command - a string that identifies the command associated with the process.
  • pid - an integer that uniquely identifies the process
  • ppid - the parent process id, unique to the parent.
  • uid - an integer that uniquely identifies the associated user.
  • gid - an integer that uniquely identifies the group the user belongs to.
  • fullPath - the full path to the executable that launched the process.
  • argv - the array of arguments passed to the executable at launch.
  • state - a string representing the current state of the process.

Using orca as an example, the structure is:

{
    command: 'orca',
    pid: 7330,
    ppid: 1315,
    uid: 1000,
    gid: 1000,
    fullPath: '/usr/bin/python3',
    argv: [ '/usr/bin/python3', '/usr/bin/orca' ],
    state: 'Sleeping'
}

The state property can have a number of values, listed below. These are grouped according to how the processReporter component sees a process as "running" vs. "not-running":

  • running:
  • "Running"
  • "Uninterruptible"
  • "Sleeping"
  • "Stopped"
  • not-running:
  • "Zombie"
  • "NoSuchProcess"

Note: "NoSuchProcess" is not returned by the nodeprocess add-on, nor the GNOME/Linux process library. If there is no process matching a pid or command, then there is no process information provided. The processReporter component adds the "NoSuchProcess" state as a special case.

Building Nodejs Bridge

Use the grunt file in the parent "linux" folder:

$ grunt shell:compileProcesses

Process Reporter Bridge

The process reporter bridge is a fluid evented component that makes use of the nodeprocesses node add-on and provides filters for locating processes by command, or by process id. There are also methods for determing if a process has changed state, and, in particular, whether the process has switched between a "running" state vs. a "not-running" state.

Most of the functionality of the bridge is in universal, since that functionality is not specific to GNOME/Linux. The interface to GNOME/Linux is handled by the "gpii.processes.native" (little) component. It has one invoker for acquiring a list of all processes. The "gpii.proccesses" (evented) component, in universal, has all the platform neutral functionality for finding specific processes, and monitoring them.

The files here are:

  • processesBridge.js - the native process component. (Note: the platform neutral code is in ".../universal/gpii/node_modules/processReporter/src/").
  • processesBridge_tests.js - unit tests for the component.
  • processReporterBridgeDemo.js - a demo script that shows the evented compontent tracking the status of the "orca" process.
  • ProcessReporter.js - for interfacing with the solutions registry.

There are two experimental features of the evented component that likely require more thought. The first of these is a reliance on setInterval() to periodically check the status of a given process. The second is a guess as to how the proces reporter could interface with the solutions registry to determine if a solution is running or not.

Events onRunStateChange and onStateChange

With respect to periodically checking for a change in process status, processesBridge (in universal) provides two events, each with methods for attaching listeners that react to changes in process status.

The onRunStateChange event is fired when a process changes from a "running" state to a "not-running" state. The method trackRunState() takes a process information structure, and a handler function as input. It sets up a periodic check of the state of the given process using the global setInterval() function. If the process status changes from "running" to "not-running" or "not-running" to "running", the given handler function is called. The trackRunState() method returns the interval identifier returned by setInterval(); however, the procesReporter provides a method stopTrackingRunState() for shutting down the entire tracking mechanics, including clearing the interval.

There is also a onStateChange event, and associated methods trackState() and stopTrackingState() that can be used to periodically check any change in state of the given prcoess, and react to the change.

A demonstration of the use of these events is provided in "processesBridgeDemo.js", using the Orca screen reader. The steps to run the demo are:

  1. $ node processesBridgeDemo.js
  2. Start a separate terminal session.
  3. In this separate terminal, start/stop Orca the way GPII does:
  • $ gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled true
  • $ gsettings set org.gnome.desktop.a11y.applications screen-reader-enabled false

As the screen-reader-enabled setting is toggled between true and false, the processesBridgeDemo will output the new (changed) state of Orca.

Interface with Solutions Registry

The process reporter also provides a preliminary way for locating processes based on "commands" as provided by the solutions registry. For each solution entry, there is an "isRunning": property that lists the function to invoke to find all processes associated with a given command name. For example the following fragment shows the "isRunning" property inside the solution entry for the Orca screen reader:

...
"org.gnome.orca": {
    "name": "ORCA Screen Reader",
    "contexts": {
        "OS": [{
            "id": "linux",
            "version": ">=2.6.26"
        }],
        "isRunning": [
            {
                "type": "gpii.processReporter.find",
                "command": "orca"
            }
        ]
    },
...