Design for Verification for Concurrent
and Distributed Software
Tevfik Bultan
Department of Computer Science
University of California, Santa Barbara
Joint Work with My Students
• Aysu Betin-Can
– Design for verification
• Tuba Yavuz-Kahveci, University of Florida, Gainesville
• Constantinos Bartzis, Carnegie Mellon University
– Action Language Verifier
– Infinite state model checking
• Xiang Fu, Georgia Southwestern State University
– Verification, realizability and synchronizability of web
service conversations
Model Checking Software
• Scalability of software model checking depends on
– Extracting compact models from programs
• This typically requires a reverse engineering step based on
user guidance and/or static analysis techniques to
– Rediscover some information about the software that
may be known at design time
• Alternative approach: Design for verification
– Structure software in ways that facilitate verification
– Document the design decisions that can be useful for
verification
– Improve the scalability of verification using this
information
A Design for Verification Approach
We have been investigating a design for verification approach
based on the following principles:
1. Using design patterns that facilitate automated verification
2. Use of stateful, behavioral interfaces which isolate the
behavior and enable modular verification
3. An assume-guarantee style verification strategy which
separates verification of the behavior from the verification
of the conformance to the interface specifications
4. A general model checking technique for interface
verification
5. Domain specific and specialized verification techniques for
behavior verification
Outline
• Design for verification for concurrent programs
– Checking correctness of synchronization
– Behavior verification using Action Language Verifier
– Interface verification using Java Path Finder and thread
isolation
• Design for verification for web services
– Checking correctness of conversations
– Behavior verification using Spin and synchronizability
analysis
– Interface verification using Java Path Finder and thread
isolation
Concurrent Programming in Java
• Java uses a variant of monitor programming
• Synchronization using locks
– Each object has a lock
synchronized(o) { ... }
• Coordination using condition variables
– Objects can be used as condition variables
synchronized (condVar){
while (!condExp) wait(condVar);
...
notifyAll(condVar);
}
Dangers in Java Concurrency
• Nested locks
synchronized m(other) { other.m(); }
run() { o1.m(o2); } run() { o2.m(o1); }
• Missed notification
notify(condVar);
• Forgotten condition check
if(!condExp) wait(condVar);
• Dependencies of condition variables can be complicated
– Conservative notification and condition check
• Inefficient
– Optimizing the notification and condition checks
• Error prone
Concurrency Controller Pattern
• A verifiable behavioral design pattern for concurrent
programs
– Defines customized synchronization policies
– Avoids usage of error-prone Java synchronization
primitives: synchronize, wait, notify
– Separates controller behavior from the threads that use
the controller
• Supports a modular verification approach which
exploits this modularity for scalable verification
Concurrency Controller Pattern Class Diagram
ThreadA ControllerInterface
SharedInterface
ThreadB
Controller ControllerStateMachine
SharedStub Shared
-var1 +action1()
+a() +a()
-var2 +action2()
+b() +b()
+Controller
+action1()
+action2() transition(){… StateTable
assert(th.state)==s;
} +transition()
a(){
assert(contr.state)==…; Action
} int GuardedCommand
+blocking()
+nonblocking()
-GuardedExecute
GuardedCommand
+guard()
+update()
This helper class
Reader-Writer Controller is provided, no
need to rewrite it
class Action{
class RWController implements protected final Object owner; …
RWInterface{
private boolean GuardedExecute(){
int nR; boolean busy;
boolean result=false;
final Action act_r_enter, act_r_exit;
for(int i=0; i=0;
initial: nr=0 and !busy;
module ReaderWriter()
enumerated state {idle, reading, writing};
initial: state=s0;
r_enter: state=idle and !busy and nr’=nr+1 and state’=reading;
r_exit: state=reading and nr’=nr-1 and state’=idle;
w_enter: state=idle and !busy and nr=0 busy’ and state’=writing;
w_exit: state=writing and !busy’ and state’=idle;
ReaderWriter: r_enter | r_exit | w_enter | w_exit;
endmodule
main: ReaderWriter() | ReaderWriter() | ReaderWriter();
spec: invariant(busy => nr=0)
spec: invariant(busy => eventually(!busy))
endmodule
Action Language Verifier
Action Language
Specification
Action Language
Parser
Composite Symbolic Library
Model Checker
Omega CUDD
Library Package MONA
Counter-example Verified Presburger BDD Automata
Arithmetic Manipulator Manipulator
Not sure
Manipulator
Composite Symbolic Library Class Diagram
Symbolic
+intersect()
+union()
+complement()
+isSatisfiable()
+isSubset()
+pre()
+post()
BoolSym IntSym CompSym
–representation: BDD –representation: Polyhedra –representation: list
+intersect() +intersect() of comAtom
+union() +union() +intersect()
• •
• •
+ union()
• • •
•
•
CUDD Library OMEGA Library compAtom
–atom: *Symbolic
Composite Symbolic Library with Extensions
Symbolic
+union()
+isSatisfiable()
+isSubset()
+forwardImage()
IntBoolAutoSym InAutotSym BoolSym HeapSym IntPolySym CompSym
–representation: –representation: –representation: –representation: –representation: –representation:
automaton automaton BDD list of ShapeGraph list of Polyhedra list of comAtom
+union() +union() +union() +union() +union() + union()
• • • •
• •
• • • •
• • •
• • •
• •
MONA CUDD shapeGraph OMEGA compAtom
–atom: *Symbolic –atom: *Symbolic
Verification for Arbitrary Number of Threads
• Counting abstraction
– Create an integer variable for each interface state
– Each variable counts the number of threads in a
particular interface state
– Automatically generate updates and guards for these
variables based on the interface specification
• Counting abstraction is automated
Readers-Writers After Counting Abstraction
module main()
integer nr;
boolean busy;
parameterized integer numReaderWriter;
restrict: nr>=0 and numReaderWriter>=1;
initial: nr=0 and !busy;
module ReaderWriter()
integer idle, reading, writing;
initial: idle=numReaderWriter;
r_enter: idle>0 and !busy and nr’=nr+1
and idle’=idle-1 and reading’=reading+1;
r_exit: reading>0 and nr’=nr-1 and reading’=reading-1
and idle’=idle+1;
w_enter: idle>0 and !busy and nr=0 and busy’
and idle’=idle-1 and writing’=writing+1;
w_exit: writing>0 and !busy’ and writing’=writing-1
and idle’=idle+1
ReaderWriter: r_enter | r_exit | w_enter | w_exit;
endmodule
main: ReaderWriter()*;
spec: invariant(busy => nr=0)
spec: invariant(busy => eventually(!busy))
endmodule
Verification of Readers-Writer Controller
Integers Booleans Cons. Time Ver. Time Memory
(secs.) (secs.) (Mbytes)
RW-4 1 5 0.04 0.01 6.6
RW-8 1 9 0.08 0.01 7
RW-16 1 17 0.19 0.02 8
RW-32 1 33 0.53 0.03 10.8
RW-64 1 65 1.71 0.06 20.6
RW-P 7 1 0.05 0.01 9.1
SUN ULTRA 10 (768 Mbyte main memory)
Example: Airport Ground Traffic Control Simulation
A simplified model of Seattle Tacoma International Airport from [Zhong 97]
Control Logic
• An airplane can land using 16R only if no airplane is using
16R at the moment
• An airplane can takeoff using 16L only if no airplane is
using 16L at the moment
• An airplane taxiing on one of the exits C3-C8 can cross
runway 16L only if no airplane is taking off at the moment
• An airplane can start using 16L for taking off only if none of
the crossing exits C3-C8 is occupied at the moment
(arriving airplanes have higher priority)
• Only one airplane can use a taxiway at a time
Controller Interface
park2 reqLand
crossRW3 exitRW3 leave
reqTakeOff
park7
crossRW4 exitRW4
park9
crossRW5 exitRW5
crossRW6 exitRW6
park10 exitRW7
crossRW7
park11 crossRW8 exitRW8
Airport Ground Traffic Control
Airport Ground Traffic Control
• Action Language specification of the controller
– Has 13 integer variables
– Has 6 Boolean variables per airplane process to keep
the local state of each airplane
– 20 actions
• Optimized Java concurrency controller class
– Has 13 integer variables
– Has 14 condition variables
– Has 34 methods
Experiments A: Arriving Airplane
D: Departing Airplane
P: Arbitrary number of threads
Processes Construction(sec) Verify-P1(sec) Verify-P2(sec) Verify-P3(sec)
2 0.81 0.42 0.28 0.69
4 1.50 0.78 0.50 1.13
8 3.03 1.53 0.99 2.22
16 6.86 3.02 2.03 5.07
2A,PD 1.02 0.64 0.43 0.83
4A,PD 1.94 1.19 0.81 1.39
8A,PD 3.95 2.28 1.54 2.59
16A,PD 8.74 4.6 3.15 5.35
PA,2D 1.67 1.31 0.88 3.94
PA,4D 3.15 2.42 1.71 5.09
PA,8D 6.40 4.64 3.32 7.35
PA,16D 13.66 9.21 7.02 12.01
PA,PD 2.65 0.99 0.57 0.43
Interface Verification
• Verification tool: Java PathFinder (JPF)
• Advantages: JPF Can check arbitrary thread
implementations
Interface Verification Steps:
• Isolate each thread implementation using stubs generated
from the controller interfaces
• Check each thread implementation separetly for interface
violations using JPF
Interface Verification
• Replace the instances of the controllers with the
corresponding stubs
– i.e., the interface state machines
• Replace the shared data protected by these controllers with
data stubs
– Interface verification will check if a user thread accesses
shared data only when it is in a correct interface state
• Significant reduction in state space
Thread Isolation
• Thread isolation assumption
– Threads only interact through the controllers and the
shared data that are protected by these controllers
• Close the environment of a thread
– User input (user interfaces)
– RMI interaction
– Network communication
– File I/O
• Check each thread implementation separately
Case Study: Concurrent Editor
• 2800 lines of Java code with
– 17 class files
– 5 controller classes
– 7 Java interfaces
• Implemented using concurrency controller pattern without
writing any Java synchronization operations
Server Client
Mediator > GUI
ServerDocument LocalDocument
Concurrent Editor
Concurrent Editor: Interface Verification
• Handling RMI methods: isolation
– Drivers: simulating incoming calls to a node
– Stubs: simulating outgoing calls to another node
• Handling GUI interactions
– Driver: simulates the user interactions
• Threads in the Server
– Threads serving RMI requests
• Threads in a Client other than main
– Event Thread capturing GUI events
– Worker Thread per paragraph
• Event thread creates Worker threads
– Less abstraction in data stubs of the Event thread
Verification Results
Behavior Verification with ALV Interface Verification with JPF
Controllers T (sec) M (MB) Threads T (sec) M (MB)
Mutex 0.01 6.00 Server 185.85 67.14
Bounded 2.05 6.47 RMI
Buffer Client 229.18 127.04
Barrier 0.01 0.5 RMI
Reader 0.42 6.94 Event 1636.62 139.48
Writer Worker 19.47 5.36
• Errors discovered (interface violation errors)
– Caused by not calling the correct controller method
before accessing the shared data
– Violation of the controller call sequence because of the
incorrectly handled exception blocks
Comments
• We applied the same approach to a larger system (TSAFE)
and used fault injection to test the effectiveness of our
approach
– We can find all the controller errors (depending on the
controller properties)
– We can find all interface errors (other than the
convoluted ones)
• Challenges
– Thread isolation
• Environment generation
– Scalability of interface verification
– Completeness of controller properties
Outline
• Design for verification for concurrent programs
– Checking correctness of synchronization
– Behavior verification using Action Language Verifier
– Interface verification using Java Path Finder
• Design for verification for web services
– Checking correctness of conversations
– Behavior verification using Spin and synchronizability
analysis
– Interface verification using Java Path Finder
Characteristics of Web Services
• Loosely coupled, interaction through standardized
interfaces
• Standardized data transmission via XML
• Asynchronous messaging
• Platform independent (.NET, J2EE)
Microsoft .Net, Sun J2EE
Implementation Platforms
Interaction WSCDL
Composition BPEL4WS
Service WSDL
Message SOAP
Type XML Schema
Data XML
Web Service Standards
An Example: Stock Analysis Service
Three peers: Investor (Inv), Stock Broker (SB), and Research
Department (RD)
• Inv initiates the stock analysis service by sending a
register message to the SB
• The SB may accept or reject the registration
• If the registration is accepted, the SB sends an analysis
request to the RD
• RD sends the results of the analysis directly to the Inv as a
report
• After receiving a report the Inv can either send an ack to
the SB or cancel the service
• Then, the SB either sends the bill for the services to the
Inv, or continues the service with another analysis
request
An Example: Stock Analysis Service (SAS)
• SAS is a composite web service
– a finite set of peers: Inv, SB, RD
– and a finite set of message classes: register, ack,
cancel, accept, reject, bill, request,
terminate, report
register
Investor ack, cancel Stock Broker
(Inv) (SB)
accept,
reject, bill
report request,
terminate
Research Dept.
(RD)
Communication Model
• We assume that the messages among the peers are
exchanged using reliable and asynchronous messaging
– FIFO and unbounded message queues
Stock Broker req req
Research Dept.
(SB) (RD)
• This model is similar to industry efforts such as
– JMS (Java Message Service)
– MSMQ (Microsoft Message Queuing Service)
Composite Web Service Execution
Investor Stock Broker Firm
!register ?register
?reject !reject
?accept !accept
!ack !request
acc
bil
rep
?report ?ack
ack
reg !bill
?bill
!cancel ?cancel
?bill !bill
!terminate
Research Dept.
?request !report
ter
req
?terminate
Conversations
• Assume that a virtual watcher records the messages as they
are sent
register
Investor accept Stock Broker
(Inv) (SB)
ack
bill
Watcher
Research Dept. reg acc req rep ack bil ter
(RD)
• A conversation is a sequence of messages the
watcher sees during an execution
Conversations and Asynchronous Communication
• We know that analyzing conversations of composite web
services is difficult due to asynchronous communication
– Model checking for conversation properties is
undecidable even for finite state peers
• The question is:
– Can we identify the composite web services where
asynchronous communication does not create a
problem?
Synchronizability Analysis
• A composite web service is synchronizable, if its
conversation set does not change
– when asynchronous communication is replaced with
synchronous communication
• If a composite web service is synchronizable we can check
its properties about its conversations using synchronous
communication semantics
– For finite state peers this is a finite state model checking
problem
Synchronizability Conditions
• Sufficient conditions for realizability (no message content)
– Synchronous compatible
• When the peers are composed synchronously, there
should not be a state where a peer is ready to send a
message while the corresponding receiver is not
ready to receive
– Autonomous
• At any state, each peer should be able to do only one
of the following: send, receive or terminate
(a peer can still choose among multiple messages)
Are These Conditions Too Restrictive?
Problem Set Size Synchronizable?
Source Name #msg #states #trans.
ISSTA’04 SAS 9 12 15 yes
CvSetup 4 4 4 yes
IBM MetaConv 4 4 6 no
Conv. Chat 2 4 5 yes
Support Buy 5 5 6 yes
Project Haggle 8 5 8 no
AMAB 8 10 15 yes
BPEL shipping 2 3 3 yes
spec Loan 6 6 6 yes
Auction 9 9 10 yes
Collaxa. StarLoan 6 7 7 yes
com Cauction 5 7 6 yes
Design for Verification Approach
Behavior
Specification Behavior Verification
Java Controller Class
In Promela
and Behavior Translator
Controller Interface Spin
based on the
Peer Controller Pattern
Synchronizability Error Trace Verified
Analysis
Interface Verification
Distributed Thread Isolation Java PathFinder
Program Program with
Stubs
Error Trace Verified
Peer Controller Pattern
• Eases the development of web services
• Uses Java API for XML messaging (JAXM)
– Asynchronous communication among peers
• Supported by a modular verification technique
– Behavior Verification: Checks properties of conversations
of a web service composed of multiple peers
• assuming that peers behave according to their
interfaces
– Interface Verification: Checks if each peer behaves
according to its interface
Peer Controller Pattern
ApplicationThread Communicator
PeerServlet
CommunicationInterface
CommunicationController
StateMachine
ThreadContainer
sessionId
Modular Verification
• Behavior Verification
– Uses synchronizability analysis
– Uses Spin model checker
• Spin model checker supports asynchronous
communication
– Automated translation to Promela
– Verifies properties of conversations
• Interface Verification
– Isolated check of individual peer implementations
– Uses program checker JPF
Behavior Verification
• Spin is a finite state model checker
– We have to bound the channel sizes, session numbers,
message types
• Synchronizability analysis
– Enables us to verify web services efficiently by replacing
communication channels with channels of size 0 (i.e.,
synchronous communication)
– The verification results hold for unbounded channels
Interface Verification
• If the call sequence to the Communicator class is accepted
by the automata specifying the interface, then the peer
implementation conforms to the behavior in the contract
• Interface Verification:
– CommunicationController is replaced with
CommunicatorInterface
– Drivers simulating other peers are automatically
generated
• State Space reduction
– Usage of stubs
– Each session is independent
• just need to check each peer for one session
Examples
• We used this approach to implement several simple web
services
– Travel agency
– Loan approver
– Product ordering
• Performance of both interface and behavior verification
were reasonable
Interface Verification
Interface Verification with JPF for Loan Approver
Threads T (sec) M (MB)
Customer 8.86 3.84
Loan 9.65 4.7
Approver
Risk 8.15 3.64
Assesor
Behavior Verification
• Sample Property: Whenever a request with a small amount
is sent, eventually an approval message accepting the loan
request will be sent.
• Loan Approval system has 154 reachable states
– because each queue length never exceeds 1.
• Behavior verification used <1 sec and 1.49 MB
• SPIN requires restricted domains
– Have to bound the channel sizes bounded message
queues
– Problem: No guarantee these results will hold for other
queue sizes
Another Example
!item1Order !item2Order ?item1Order ?item2Order
!payReq ?payReq
?receipt ?bill !receipt !bill
!payment ?payment
• SPIN runs out of memory for message queue size 15!
– Absence of error for queue size 15 does not ensure
correctness
– Reachable state space is infinite
• Issue is not only unbounded queues, but also efficiency
• Solution: We use synchronizability analysis
– The example above and Loan Approver are both
synchronizable
Comments
• We were able to use our design for verification approach
based on design patterns and behavioral interfaces in
different domains
• Use of domain specific behavior verification techniques has
been very effective
• Interface verification is challenging
• Model checking research resulted in various verification
techniques and tools which can be customized for specific
classes of software systems
• Automated verification techniques can scale to realistic
software systems using design for verification approach
References
• Design for Verification
[Betin-Can, Bultan SoftMC03, ASE04, WWW05, ICWS05]
• Action Language Verifier
[Bultan ICSE 00], [Bultan, Yavuz-Kahveci ASE 01], [Yavuz-Kahveci, Bar,
Bultan CAV 2005]
• Composite Symbolic Library
[Yavuz-Kahveci, Tuncer, Bultan TACAS01], [Yavuz-Kahveci, Bultan FroCos
02, STTT 03]
• Realizability and Synchronizability of Web Services
[Bultan, Fu, Hull, Su WWW03], [Fu, Bultan, Su CIAA03, TCS04, WWW04,
ICWS04]
• Infinite State Model Checking
[Bar Bultan CIAA02, IJFCS03, CAV03,CAV04]
Related Work: Design for Verification
• Design for Verification
– [Magee, Kramer 99]
• uses LTSA model checker for verification of finite state models
of Java concurrent programs
– [Sharygina, Browne, Kurshan FASE 01]
• presents design rules for object-oriented design models to
facilitate verification
– [Mehlitz, Penix Workshop on Component-Based Soft. Eng. 03]
• promotes using design patterns and exploiting their properties in
verification
• Design patterns for concurrency
– [Schmidt, Stal, Rohmert, Buschmann 00], [Lea 99], [Grand 02]
• Environment extraction/generation
– [Godefroid, Colby, Jagadeesan PLDI 98], [Tkachuk, Dwyer ASE 03],
[Tkachuk, Dwyer, Pasareanu ESEC/FSE 03]
Related Work: Model Checking Programs
• Verisoft from Bell Labs [Godefroid POPL 97]
– C programs, handles concurrency, bounded search, bounded
recursion, stateless search
• Java Path Finder (JPF) at NASA Ames [Havelund, Visser]
– Explicit state model checking for Java programs, bounded search,
bounded recursion, handles concurrency
• SLAM project at Microsoft Research
[Ball, Rajamani et al. SPIN 00, PLDI 01]
– Symbolic model checking for C programs, unbounded recursion, no
concurrency
– Uses predicate abstraction [Saidi, Graf 97] and BDDs
• BANDERA: A tool for extracting finite state models from programs
[Dwyer, Hatcliff et al ICSE 00, 01]
• Modular model checking of software components
– [Chaki, Clarke, Groce, Jha, Veith ICSE 03]
Related Work: Web Services
• Conversation specification
– IBM Conversation support project
http://www.research.ibm.com/convsupport/
– Conversation support for business process integration [Hanson,
Nandi, Kumaran EDOCC’02]
– Orchestrating computations on the world-wide web [Choi, Garg, Rai,
Misram, Vin EuroPar’02]
• Realizability problem
– Realizability of Message Sequence Charts (MSC) [Alur, Etassami,
Yannakakis ICSE’00, ICALP’01]
Related Work: Web Services
• Verification of web services
– Simulation, verification, composition of web services using a Petri
net model [Narayanan, McIlraith WWW’02]
– BPEL verification using a process algebra model and Concurrency
Workbench [Koshkina, van Breugel TAV-WEB’03]
– Using MSC to model BPEL web services which are translated to
labeled transition systems and verified using model checking
[Foster, Uchitel, Magee, Kramer ASE’03]
– Model checking Web Service Flow Language specifications using
Spin [Nakajima ICWE’04]
• Conformance checking for asynchronously communicating processes
– [Rajamani, Rehof CAV’02]
• conformance checking between specification model and a model
extracted from the implementation