Static Deadlock Detection for Java Libraries Amy Williams, William Thies, and Michael D. Ernst Massachusetts Institute of Technology.

Slides:



Advertisements
Similar presentations
Dataflow Analysis for Datarace-Free Programs (ESOP 11) Arnab De Joint work with Deepak DSouza and Rupesh Nasre Indian Institute of Science, Bangalore.
Advertisements

Global States.
50.003: Elements of Software Construction Week 6 Thread Safety and Synchronization.
1 Lecture 11: Transactions: Concurrency. 2 Overview Transactions Concurrency Control Locking Transactions in SQL.
Effective Static Deadlock Detection
CS3771 Today: deadlock detection and election algorithms  Previous class Event ordering in distributed systems Various approaches for Mutual Exclusion.
Concurrency: Deadlock and Starvation Chapter 6. Deadlock Permanent blocking of a set of processes that either compete for system resources or communicate.
Abstraction and Modular Reasoning for the Verification of Software Corina Pasareanu NASA Ames Research Center.
Pointer Analysis – Part I Mayur Naik Intel Research, Berkeley CS294 Lecture March 17, 2009.
Goldilocks: Efficiently Computing the Happens-Before Relation Using Locksets Tayfun Elmas 1, Shaz Qadeer 2, Serdar Tasiran 1 1 Koç University, İstanbul,
Verification of Multithreaded Object- Oriented Programs with Invariants Bart Jacobs, K. Rustan M. Leino, Wolfram Schulte.
A Randomized Dynamic Program Analysis for Detecting Real Deadlocks Koushik Sen CS 265.
Liveness and Performance Issues
Chapter 6: Process Synchronization
Silberschatz, Galvin and Gagne ©2009 Operating System Concepts – 8 th Edition, Chapter 6: Process Synchronization.
/ PSWLAB Concurrent Bug Patterns and How to Test Them by Eitan Farchi, Yarden Nir, Shmuel Ur published in the proceedings of IPDPS’03 (PADTAD2003)
Taming Win32 Threads with Static Analysis Jason Yang Program Analysis Group Center for Software Excellence (CSE) Microsoft Corporation.
Avishai Wool lecture Introduction to Systems Programming Lecture 5 Deadlocks.
Atomicity in Multi-Threaded Programs Prachi Tiwari University of California, Santa Cruz CMPS 203 Programming Languages, Fall 2004.
/ PSWLAB Atomizer: A Dynamic Atomicity Checker For Multithreaded Programs By Cormac Flanagan, Stephen N. Freund 24 th April, 2008 Hong,Shin.
Mayur Naik Alex Aiken John Whaley Stanford University Effective Static Race Detection for Java.
OOP in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
© Andy Wellings, 2004 Roadmap  Introduction  Concurrent Programming  Communication and Synchronization  Completing the Java Model  Overview of the.
Language Support for Lightweight transactions Tim Harris & Keir Fraser Presented by Narayanan Sundaram 04/28/2008.
Instructor: Umar KalimNUST Institute of Information Technology Operating Systems Process Synchronization.
Cormac Flanagan UC Santa Cruz Velodrome: A Sound and Complete Dynamic Atomicity Checker for Multithreaded Programs Jaeheon Yi UC Santa Cruz Stephen Freund.
Register Allocation and Spilling via Graph Coloring G. J. Chaitin IBM Research, 1982.
Introduction to Java Programming Language Junji Zhi University of Toronto 1.
Memory Management for Real-Time Java Wes Beebee and Martin Rinard Laboratory for Computer Science Massachusetts Institute of Technology Supported by: DARPA.
Maria-Cristina Marinescu Martin Rinard Laboratory for Computer Science Massachusetts Institute of Technology A Synthesis Algorithm for Modular Design of.
Rahul Sharma (Stanford) Michael Bauer (NVIDIA Research) Alex Aiken (Stanford) Verification of Producer-Consumer Synchronization in GPU Programs June 15,
Modern Concurrency Abstractions for C# by Nick Benton, Luca Cardelli & C´EDRIC FOURNET Microsoft Research.
50.003: Elements of Software Construction Week 8 Composing Thread-safe Objects.
Threading and Concurrency Issues ● Creating Threads ● In Java ● Subclassing Thread ● Implementing Runnable ● Synchronization ● Immutable ● Synchronized.
Development of a Resource Locking Algorithm for a Kernel Debugging User-space API Library TJHSST Computer Systems Lab Timothy Wismer.
1 Effective Static Race Detection for Java Mayur, Alex, CS Department Stanford University Presented by Roy Ganor 14/2/08 Point-To Analysis Seminar.
EECE 310: Software Engineering Iteration Abstraction.
Chapter 10: File-System Interface 10.1 Silberschatz, Galvin and Gagne ©2011 Operating System Concepts – 8 th Edition 2014.
/ PSWLAB Type-Based Race Detection for J AVA by Cormac Flanagan, Stephen N. Freund 22 nd Feb 2008 presented by Hong,Shin Type-Based.
Java Threads 11 Threading and Concurrent Programming in Java Introduction and Definitions D.W. Denbo Introduction and Definitions D.W. Denbo.
Use of Coverity & Valgrind in Geant4 Gabriele Cosmo.
Type Systems CS Definitions Program analysis Discovering facts about programs. Dynamic analysis Program analysis by using program executions.
Optimistic Design 1. Guarded Methods Do something based on the fact that one or more objects have particular states  Make a set of purchases assuming.
Colorama: Architectural Support for Data-Centric Synchronization Luis Ceze, Pablo Montesinos, Christoph von Praun, and Josep Torrellas, HPCA 2007 Shimin.
© 2006 Pearson Education 1 More Operators  To round out our knowledge of Java operators, let's examine a few more  In particular, we will examine the.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
A Universe-Type-Based Verification Technique for Mutable Static Fields and Methods Alexander J Summers Sophia Drossopoulou Imperial College London Peter.
Chapter 6 Introduction to Defining Classes. Objectives: Design and implement a simple class from user requirements. Organize a program in terms of a view.
15.1 Threads and Multi- threading Understanding threads and multi-threading In general, modern computers perform one task at a time It is often.
SPL/2010 Synchronization 1. SPL/2010 Overview ● synchronization mechanisms in modern RTEs ● concurrency issues ● places where synchronization is needed.
The Singleton Pattern SE-2811 Dr. Mark L. Hornick 1.
Session 13 Pinball Game Construction Kit (Version 3):
Exceptions and Assertions Chapter 15 – CSCI 1302.
Effective Static Deadlock Detection Mayur Naik* Chang-Seo Park +, Koushik Sen +, David Gay* *Intel Research, Berkeley + UC Berkeley.
Deadlock Bug Detection Techniques Prof. Moonzoo Kim CS KAIST CS492B Analysis of Concurrent Programs 1.
PROGRAMMING TESTING B MODULE 2: SOFTWARE SYSTEMS 22 NOVEMBER 2013.
Chapter 7: Deadlock Course Administration n Midterm exam next week in class l Closed book n Final exam time changed to during class.
Effective Static Deadlock Detection Mayur Naik (Intel Research) Chang-Seo Park and Koushik Sen (UC Berkeley) David Gay (Intel Research)
The Singleton Pattern (Creational)
Concurrency (Threads) Threads allow you to do tasks in parallel. In an unthreaded program, you code is executed procedurally from start to finish. In a.
Tutorial 3: Homework 2 and Project 2
The Singleton Pattern SE-2811 Dr. Mark L. Hornick.
The Echo Algorithm The echo algorithm can be used to collect and disperse information in a distributed system It was originally designed for learning network.
Amir Kamil and Katherine Yelick
Static Deadlock Detection for Java Libraries
Atomicity in Multithreaded Software
Chapter 10 Transaction Management and Concurrency Control
Chapter 10: File-System Interface
Amir Kamil and Katherine Yelick
Synchronization and liveness
Presentation transcript:

Static Deadlock Detection for Java Libraries Amy Williams, William Thies, and Michael D. Ernst Massachusetts Institute of Technology

Deadlock Each deadlocked thread attempts to acquire a lock held by another thread –Can halt entire program execution –Difficult to expose during testing –Once exposed, difficult to replicate Example: Thread 1: a.append(b); locks a, b Thread 2: b.append(a); locks b, a a b StringBuffer a, b;

Deadlock in Libraries Library writers may wish to provide guarantees –JDK’s StringBuffer documentation says class is thread-safe Goal: find client calls that deadlock library or verify that none exist

Analyzing Programs / Libraries For Programs:For Libraries: Method Calls Fixed Consider all calling patterns Aliasing Possibilities Fixed Consider aliasing induced by any program Number of Threads Might be knownUnbounded

Deadlock from Sun’s JDK import java.beans.beancontext.*; BeanContextSupport support = new BeanContextSupport(); Object source = new Object(); PropertyChangeEvent event = new PropertyChangeEvent(source, "beanContext",...); support.add(source); support.vetoableChange(event); Thread 1: support.propertyChange(event); locks global, field Thread 2: support.remove(source); locks field, global Also found 13 other deadlocks

Analysis Overview 1.Build lock-order graph representing locking behavior of each method in library 2.Combine graphs for all public methods into single graph 3.Detect cycles in this graph, which indicate deadlock possibilities Analysis properties: reports all deadlocks, context-sensitive, flow-sensitive

JDK Source (simplified) interface BeanContext { public static final Object globalHierarchyLock; } class BeanContextSupport { protected HashMap children; public boolean remove(Object targetChild) { synchronized(BeanContext.globalHierarchyLock) {... synchronized(children) { children.remove(targetChild); }... }... } Object HashMap Continued...

JDK Source (simplified), cont. class BeanContextSupport { protected HashMap children; public void propertyChange(PropertyChangeEvent pce) {... Object source = pce.getSource(); synchronized(children) { if (...) {... remove(source);... } Object HashMap public boolean remove(Object targetChild) { synchronized (BeanContext.globalHierarchyLock) {... }

Merged Graph When merged, graphs indicate possible locking orders of all methods Cycles indicate possible deadlock –Expose cases in which threads lock set of locks in different (conflicting) orders Object HashMap

Outline Introduction Deadlock Detection Algorithm Results Related Work and Conclusions

Synchronization in Java Locking is hierarchical, performed using synchronized statement –Multiple locks acquired via nested synchronized statements Synchronizing on previously acquired lock always succeeds –Considered a no-op for our analysis Synchronized methods sugar for synchronizing on this synchronized (lock1) { synchronized (lock2) {... }

Synchronization in Java wait() and notify() methods described in paper Java 1.5’s non-hierarchical primitives (in java.concurrent package) not covered by analysis –Usage rare; recommended only for expert programmers

Analysis Overview 1.Build lock-order graph representing locking behavior of each method in library Callee graphs integrated into caller Iterate to fixed point; termination guaranteed 2.Combine graphs for all public methods into single graph 3.Detect cycles in this graph, which indicate deadlock possibilities

Lock-order Graph Directed graph that represents the order in which locks are acquired Nodes represent may-alias sets –Allows graphs from different methods to be combined Edges mean the source lock held while destination lock acquired Cycles indicate possibility of deadlock set 1 set 3set 2

Example Library public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [] public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [] public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [b1] b1 No locks held, so node is root public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [b1] b1 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [b1, c1] b1 c1 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [b1, c1] b1 c1 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: deposit() Graph: Ordered list of locks held: [b1] b1 c1 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Lock-order graph for deposit() Graph: b1 c1 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Example Analysis: openAccount() Graph: Ordered list of locks held: [] public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Example Analysis: openAccount() Graph: Ordered list of locks held: [b2] b2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Example Analysis: openAccount() Graph: Ordered list of locks held: [c2] b2c2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Example Analysis: openAccount() Graph: Ordered list of locks held: [c2] b2c2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Example Analysis: openAccount() Graph: Ordered list of locks held: [c2] public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph:current graph: b1 c1 b2c2

Graph: Ordered list of locks held: [c2] b1b2 Call to deposit(): update copy of deposit’s graph ^ c1 b2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph:current graph: b1 c1 b2c2

Graph: Ordered list of locks held: [c2] b2 Call to deposit(): update copy of deposit’s graph ^ deposit’s graph:current graph: c1 c2 b1 c1 b2c2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Graph: Ordered list of locks held: [c2] b2 Call to deposit(): update copy of deposit’s graph ^ c2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph:current graph: b1 c1 b2c2

Graph: Ordered list of locks held: [c2] b2 Call to deposit(): update copy of deposit’s graph ^ b2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph:current graph: b1 c1 b2c2

Graph: Ordered list of locks held: [c2] Call to deposit(): insert deposit’s graph b2 c2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Graph: Ordered list of locks held: [c2] Call to deposit(): insert deposit’s graph b2c2 b2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Graph: Lock-order graph for openAccount() b2c2 public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); } deposit’s graph: b1 c1

Analysis Overview 1.Build lock-order graph representing locking behavior of each method in library Callee graphs integrated into caller Iterate to fixed point; termination guaranteed 2.Combine graphs for all public methods into single graph 3.Detect cycles in this graph, which indicate deadlock possibilities

Combine Graphs Graph for deposit():Graph for openAccount(): b1 c1 b2c2

Combine Graphs Graph for deposit():Graph for openAccount(): BankClient Bank

Combine Graphs Graph for deposit():Graph for openAccount(): BankClient Bank Final graph:

Analysis Overview 1.Build lock-order graph representing locking behavior of each method in library Callee graphs integrated into caller Iterate to fixed point; termination guaranteed 2.Combine graphs for all public methods into single graph 3.Detect cycles in this graph, which indicate deadlock possibilities

Cycle in Combined Graph Cycles indicate possibility of deadlock, and deadlock is possible BankClient Final graph:

Code that Deadlocks Library Thread 2: deposit(b, c); locks b, c Thread 1: openAccount(b, c); locks c, b Bank b; Client c; public void deposit(Bank b1, Client c1) { synchronized (b1) { synchronized (c1) {... } public void openAccount(Bank b2, Client c2) { synchronized (b2) {... } synchronized (c2) { deposit(b2, c2); }

Improving Precision We further refine may-alias sets and type information in certain cases (see paper) –Unaliased fields –Caller / callee type resolution –Final and effectively-final fields These optimizations prove very effective: one library went from 909 reports to only 1 Context-sensitivity (integrating callee graphs) greatly improved precision

Outline Introduction Deadlock Detection Algorithm Results Related Work and Conclusions

Deadlocks Detected Analysis is sound: detects all deadlocks in library under analysis Assumptions: –Clients assumed to respect lock order of library for any shared locks –Callbacks are not modeled The client code may call any public method Would introduce many locking orders which are unlikely in practice –Reflection not handled

Deadlock Reports Each report: set of variables possibly involved in deadlock Also provided: set of methods possibly deadlocking using those variables –Sometimes many call sequences per report

Results: Overview Analyzed 18 libraries 13 libraries verified to be deadlock-free –Each library analyzed in under 3 minutes 5 libraries not verified –Exhibited 14 distinct deadlocks –Each library analyzed in under 3 minutes employing filtering heuristics

Deadlock-Free Libraries Library sync kLOCReports jcurzez2441 httpunit17230 jasperreports11670 croftsoft11142 dom4j6411 cewolf670 jfreechart51250 htmlparser5220 jpcap480 treemap470 PDFBox2280 UJAC1630 JOscarLib160

Deadlock-Free Libraries Library sync kLOCReports jcurzez2441 httpunit17230 jasperreports11670 croftsoft11142 dom4j6411 cewolf670 jfreechart51250 htmlparser5220 jpcap480 treemap470 PDFBox2280 UJAC1630 JOscarLib160

Deadlock-Free Libraries Library sync kLOCReports jcurzez2441 httpunit17230 jasperreports11670 croftsoft11142 dom4j6411 cewolf670 jfreechart51250 htmlparser5220 jpcap480 treemap470 PDFBox2280 UJAC1630 JOscarLib160 Manually verified 4 reports to be false positives

Non-verified Libraries Library sync kLOCReports Deadlocks Found JDK Out of Memory 7 Classpath Out of Memory 5 ProActive19963≥ 1962 Jess11127≥ 2690 sdsu6926≥ 20,4790 Deadlocked JVM for all 14 cases

Filtering Heuristics Full analysis can yield too many reports Cycle length –Do not report cycles longer than 2 nodes Assume runtime type same as declared type –Lock declared as Object cannot alias with subclasses May filter out real deadlocks

Non-verified Libraries Library sync kLOCReports Reports (Filtered) Deadlocks Found JDK Out of Memory 707 Classpath Out of Memory 325 ProActive19963≥ Jess11127≥ sdsu6926≥ 20,47930 Deadlocked JVM for all 14 cases

Non-verified Libraries Library sync kLOCReports Reports (Filtered) Deadlocks Found JDK Out of Memory 707 Classpath Out of Memory 325 ProActive19963≥ Jess11127≥ sdsu6926≥ 20,47930 Deadlocked JVM for all 14 cases

Deadlocks Found JDKClasspath BeanContextSupport × StringBuffer×× synchronized Collections×× PrintWriter/CharArrayWriter× java.awt.dnd.DropTarget× java.awt.EventQueue×× java.awt.Menu× java.util.SimpleTimeZone× java.util.logging.Logger× ProActive: ProxyForGroup, AbstractDataObject

ProActive’s ProxyForGroup ProxyForGroup method asynchronousCallOnGroup() can be made to lock both this and any other ProxyForGroup object –Complicated state required to produce this scenario

Cyclic Deadlocks java.util.Vector can be deadlocked by forming a cycle with two Vector instances Similar deadlock in –All other synchronized Collections –Combinations of those Collections This deadlock only counted once for JDK and Classpath –5 other deadlocks Thread 1: v1.contains(o); locks v1, v2 Vector v1, v2; Object o; v1.add(v2); v2.add(v1); Thread 2: v2.contains(o); locks v2, v1 v1v2

Outline Introduction Deadlock Detection Algorithm Results Related Work and Conclusions

Related Work Using lock-order graphs: –Jlint [Artho, Biere 2001]; von Praun 2004 –For programs, do not detect all deadlocks RacerX [Engler, Ashcraft 2003] –Non-hierarchical locking (for C), requires annotations, does not detect all deadlocks Model Checking: –Demartini, Iosif, Sisto 1999 –Java Pathfinder: Havelund, Pressburger 2000 –For programs, not scalable Ownership Types: –Boyapati, Lee, Rinard 2002 –Requires annotations, restricts programming model

Conclusions Our analysis is effective at –Verifying libraries to be free from deadlock –Finding deadlocks Analysis of libraries can be effective at finding library specific defects

Sources of Imprecision Consider infeasible aliasing / sharing across threads –Do not track flow of values through fields Consider infeasible paths of control

Resolving Deadlocks Two possible solutions: –Rewrite methods to acquire locks in set order –Extend Java with synchronization primitive to atomically acquire multiple locks (can also write this as a library method) Issue: must know locks –Can sometimes write helper methods to determine locks –Locks may change while being determined Global lock or transactions are alternatives