Did you know ... | Search Documentation: |
![]() | Pack canny_tudor -- prolog/os/apps.pl |
What is an app? In this operating-system os_apps
module context,
simply something you can start and stop using a process. It has no
standard input, and typically none or minimal standard output and
error.
There is an important distinction between apps and processes. These predicates use processes to launch apps. An application typically has one process instance; else if not, has differing arguments to distinguish one running instance of the app from another. Hence for the same reason, the app model here ignores "standard input." Apps have no such input stream, conceptually speaking.
Is "app" the right word to describe such a thing? English limits the alternatives: process, no because that means something that loads an app; program, no because that generally refers the app's image including its resources.
Apps start by creating a process. Processes have four distinct specification parameter groups: a path specification, a list of arguments, possibly some execution options along with some optional encoding and other run-time related options. Call this the application's configuration.
The os_apps
predicates rely on multi-file property_for_app/2 to
configure the app launch path, arguments and options. The
property-for-app predicate supplies an app's configuration
non-deterministically using three sub-terms for the first Property
argument, as follows.
property_for_app(path(Path), App)
property_for_app(argument(Argument), App)
property_for_app(option(Option), App)
Two things to note about these predicates; (1) App is a compound describing the app and its app-specific configuration information; (2) the first Property argument collates arguments and options non-deterministically. Predicate app_start/1 finds all the argument- and option-solutions in the order defined.
By default, starting an app does not persist the app. It does not restart if the user or some other agent, including bugs, causes the app to exit. Consequently, this module offers a secondary app-servicing layer. You can start up or shut down any app. This amounts to starting and upping or stopping and downing, but substitutes shut for stop. Starting up issues a start but also watches for stopping.
Sends three broadcast messages for any given App, as follows:
app_started(App)
app_decoded(App, stdout(Codes))
app_decoded(App, stderr(Codes))
app_stopped(App, Status)
Running apps send zero or more os:app_decoded(App, Term)
messages,
one for every line appearing in their standard output and standard
error streams. Removes line terminators. App termination broadcasts
an exit(Code)
term for its final Status.
Note that app_property(App, defined)
should not throw an
exception. Some apps have an indeterminate number of invocations
where App is a compound with variables. Make sure that the necessary
properties are ground, rather than unbound.
Collapses non-determinism to determinism by collecting App and Property pairs before expanding the bag to members non-deterministically.
Options can include the following:
Checks for not-running after unifying with the App path. Succeeds if already running.
Killing does not retract the app_pid/2 by design. Doing so would trigger a failure warning. (The waiting PID-monitor thread would die on failure because its retract attempt fails.)
Semantics of this predicate rely on app_start/1 succeeding even if
already started. That way, you can start an app then subsequently
up it, meaning stay up. Hence, you can app_stop(App)
to force a
restart if already app_up(App)
. Stopping an app does not down it!
Note that app_start/1 will fail for one of two reasons: (1) because the App has not been defined yet; (2) because starting it fails for some reason.