Specification-based runtime monitoring  checks a program’s execution trace against a formal specification. Often more rigorous than testing due to the presence of a formal specification, this technique is also computationally much cheaper than formal verification methods like model checking, as it only needs to look at concrete program runs with instrumentation.  is a language based on Hoare’s Communicating Sequential Processes  for developing the formal specification. Unlike many other languages in this niche, can directly express concurrency. Moreover, it builds up the specification in a bottom-up manner by composing smaller, interacting components, helping to model complex behavior.
’s main appeal as a specification language, compared to plain CSP, is a FAIL construct that signals a global failure, aborting all processes in the model at once. This construct can be used like assert(false) in C or Java, allowing to code invariants that mark some states as (should-be) unreachable. By contrast, deadlocks and livelocks, the conventional notions of failure in CSP, affect only the deadlocked or livelocked process(es). These failures are thus very difficult to propagate into a failure for the entire system, as desired for assertion failures. However, the semantics of how FAIL propagates throughout the model requires special treatment. Because the propagation preempts all other activities, normal execution rules must apply only when FAIL is not currently propagating. This is a negative constraint, which is generally problematic .
While earlier work  demonstrated a trace semantics and a reasonably efficient implementation for , an operational semantics has been lacking. Developing an operational semantics is highly desirable for several reasons. Firstly, though a trace semantics more naturally defines the set of behaviors (i.e. traces) that comply with a specification, an operational semantics more directly defines the implementation. Secondly, process algebras admit multiple denotational semantics capturing different aspects of operationally defined behavior . Investigating the full spectrum of such semantics requires an operational semantics. Finally, an operational semantics provides a more accessible presentation of the semantics than denotational semantics.
In this paper, after reviewing the syntax and trace semantics of (Section 2), we present the following contributions.
We prove that the operational semantics induces the previously published trace semantics (Section 4).
2 Syntax and Trace Semantics of
|Event Set||where is computable|
|Event Set Param|
This section reviews the syntax and trace semantics of . Figure 1 presents the syntax. A term represents a process, which is an entity that successively emits events drawn from an alphabet . Terms are built from the following constructs, with the indicated meanings. For a thorougher explanation, see .
The stuck term STOP does not emit anything.
The failing term FAIL aborts all processes.
Prefix chooses and emits an event , then executes .
Choice executes or , whichever manages to emit something first.
Parallel composition executes and in parallel. Their events are interleaved arbitrarily, except events in are synchronized.
An event set can be specified by any computable function parametrized by the ’s bound by surrounding prefix operators.
In this short paper, we omit recursion and the terminating action in the interest of conciseness. This paper’s focus is on analyzing FAIL, and complicates the presentation substantially without adding anything of conceptual significance. Recursion seems to be similar, though it is still under investigation.
|Trace Set Operations|
Figure 2 presents the trace semantics. A trace is a (possibly empty) sequence of events, and is the set of all traces. The concatenation of traces and is written . A trace set is any prefix-closed set of traces, which can be empty, unlike in conventional process algebras. The trace semantics of assigns to each term a trace set , which is intuitively the set of traces can emit.
The semantic map uses some operations on trace sets. If is a trace set, prepends to all members of and adjoins , while discards all traces in that do not start with and drops the leading from all remaining traces. The operator is defined by eqs. 2 and 1. Though significantly simplified, these equations are equivalent to the ones found in  modulo the absence of . In , this operator was defined “coinductively”, which was correct but misleading. Formally, by the Knaster-Tarski Theorem, the defining equations (1) and (2) have a greatest solution in the complete lattice of total binary functions on TraceSets ordered by point-wise inclusion, which was taken to be . However, if and are any two solutions of these equations, then for any and , every trace in is also in , by straightforward induction on the trace’s length. Thus, the solution is unique, and is this unique solution.
3 Operational Semantics
|e ∈E(?x:E →P) e↦ [e/x]P P τ↦ P’P□Q τ↦ P’□Q Q τ↦ Q’P□Q τ↦ P□Q’ P e↦ P’P□Q e↦ P’ Q e↦ Q’P□Q e↦ Q’ P a↦ P’ a ／∈EP——_E^Q a↦ P’ ——_E^Q sep=1.5em Q a↦ Q’ a ／∈E^P——_EQ a↦ ^P ——_EQ’ ^P e↦ P’^Qe↦ Q’ e ∈E^P——_E^Q e↦ P’ ——_EQ’ D_1 τ↦ P_1D_1——_ED_2 τ↦ P_1 ——_ED_2 D_2 τ↦ P_2D_1——_ED_2 τ↦ D_1 ——_EP_2 FAIL□FAILτ↦ FAIL FAIL——_EP τ↦ FAIL P ——_EFAILτ↦ FAIL P ε⤇ P P a↦ P’ s⤇ P”Pas⤇ P” P τ↦ P’ s⤇ P”P s⤇ P”|
This section presents the operational semantics. The semantics is given in Figure 3, which defines internal transitions between terms. Some transitions do not emit events but instead emit the silent action . A visible transition happens when internally transitions to in zero or more steps, and the non- actions it emits along the way forms .
The main challenge in this semantics is capturing the propagation of FAIL. For example, in , the must not be allowed to keep emitting events, for then could do so indefinitely, withholding the propagation of FAIL. Instead, FAIL should kill all processes including , transitioning the whole term to FAIL. To achieve this effect, the usual rule that allows the left operand to transition must apply only when the right operand is not failing. This constraint is tricky to capture because it is a negative constraint.
In our semantics, the constraint is captured by the viability annotation . This annotation restricts the range of the metavariable to exclude doomed terms, i.e. terms for which transitioning to FAIL has become inevitable and are now propagating FAIL within themselves. These annotations are placed so that when a term is doomed, rules that propagate FAIL become the only applicable ones, thus forcing the propagation to take place.
A doomed process always transitions to FAIL while emitting nothing but .
implies , where denotes term size, by induction on . Thus, a doomed term can only -transition, and only finitely many times, while staying doomed. Another induction shows , so a doomed term keeps transitioning until it reaches FAIL.
4 Correspondence Between the Semantics
This section establishes a correspondence between the two semantics: a process’ denotation is precisely the set of traces it can emit, up to but not including any transitions that doom the process. This means that the monitor comparing a system to can declare a failure as soon as the system’s trace strays out of .
A special case of this theorem is particularly illuminating: the doomed set is precisely the set of terms with empty trace sets, corresponding to the fact that doomed terms silently transition to FAIL.
Induction on .
Furthermore, trace sets faithfully follow non-silent transitions, in that the traces which follow an event in are precisely the traces of terms that follow after a sequence of transitions that emit .
Induction on the size of , where event sets do not count toward size, e.g. . This way, , so when , the inductive hypothesis applies to , despite it not being a subterm. Several lemmas are needed along the way, two of which are of particular note. Take for example with and . Inductive hypotheses give . Then, continuity (Lemma 1) lets us commute the and , equating this to . Then, a lemma characterizing those with equates this to .
Theorem 4.1 is a straightforward consequence of these facts.
Proof (of Theorem 4.1)
We show by induction on . For the base case, by Proposition 2. If , then , and if , then can only transition inside Doomed as noted in the proof of Proposition 1. For the inductive step, breaks down as , and . By Lemma 2, this is equivalent to having and for some , which by inductive hypothesis is equivalent to .
5 Related Works
The main issue with semantics is the propagation of FAIL, which entails the negative constraint that normal computation rules apply only if FAIL-propagation rules do not. Negative premises of the form come quite naturally as a means for codifying such constraints, but negative premises are generally quite problematic. A transition relation satisfying negative rules may be not-existent, or non-unique, with no obvious guiding principle (such as minimality) in choosing the “right” one. Some formats do guarantee well-definedness, such as GSOS with the witnessing constraint  and ntyft/ntyxt . But even then, negative rules tend to betray desirable properties such as compositionality of some forms of bisimulation .
Our approach exploits the fact that we only have a very specific negative constraint – the absence of doomed subprocesses – and encodes it with a restriction on the range of metavariables in transition rules. With trick, we manage to avoid negative premises altogether, essentially turning the system into a positive one. This approach is very commonly employed, e.g. in reduction rules for the call-by-value calculus , where the argument in a function application should be evaluated only if the function expression cannot be evaluated any further.
We identify FAIL-induced failures by transitions into FAIL, but an alternative approach would be to have FAIL emit a special event , just as termination is signalled by . Though we have not pursued this idea in detail, the central concern there will be to give higher priority than all other events. Prioritized transition also involves a negative constraint but is known to be quite well-behaved, being translatable to plain CSP 
. At the moment, it is not clear ifFAIL propagation can be translated to the prioritized-transition primitive in .
We gave an operational semantics for that adequately captures the behavior of FAIL, the global failure operator, with positive operational rules. This semantics induces the previously defined trace semantics. As noted in the introduction, this development enables studies of other types of denotational semantics, while informing the implementation. An interesting direction of future work is to see if FAIL can be specified by priorities, and if that approach yields better-behaved semantics.
The authors would like to thank Yoshinao Isobe for comments on an earlier draft of this paper and stimulating discussions.
-  Bloom, B.: Structural operational semantics for weak bisimulations. Theoretical Computer Science 146(1), 25–68 (1995)
-  Bloom, B., Istrail, S., Meyer, A.R.: Bisimulation can’t be traced. Journal of the ACM 42(1), 232–268 (1995)
-  van Glabbeek, R.J.: The linear time - branching time spectrum I. The semantics of concrete, sequential processes, chap. 1, pp. 3–100. Elsevier (2001)
-  Groote, J.F.: Transition system specifications with negative premises. Theoretical Computer Science 118(2), 263 – 299 (1993)
-  Havelund, K., Reger, G.: Specification of parametric monitors, pp. 151–189. Springer Fachmedien Wiesbaden, Wiesbaden (2015)
-  Hoare, C.A.R.: Communicating Sequential Processes. Prentice-Hall, Inc., Upper Saddle River, NJ, USA (1985)
-  Mitchell, J.C.: Foundations for Programming Languages. MIT Press (1996)
-  Plotkin, G.D.: A structural approach to operational semantics. The Journal of Logic and Algebraic Programming 60, 17–139 (2004)
-  Roscoe, A.: The expressiveness of CSP with priority. Electronic Notes in Theoretical Computer Science 319, 387 – 401 (2015)
-  Yamagata, Y., Artho, C., Hagiya, M., Inoue, J., Ma, L., Tanabe, Y., Yamamoto, M.: Runtime Monitoring for Concurrent Systems, pp. 386–403. Springer International Publishing, Cham (2016)