Você está na página 1de 15

Task:

Implement the Lock Tree Algorithm in Java.

Deadline: Nov 9

System Setup
We will test your code in the following setup:

Ubuntu 16.04

java version “9” (oracle)

Intro
In this assignment, you will implement the Locktree algorithm in Java.

The assignment has three tasks:

1. Implement Locktree algorithm that uses CustomLock

<!-- during the interview only: describe the cases:

when LT misses a deadlock

reports a spurious deadlock

when any dynamic algorithm would miss a deadlock? --

>

2. javassist : implement Instrumenter that tracks calls to

lock() and unlock() .

3. Using your Instrumenter and our LockTreeExecuter ,

analyse deadlocks in our FTP server.

<!–

In the first task,


we provide the skeleton of a lock class derived from Java’s

ReentrantLock

(see vt.locktree.CustomLock ).

This special lock tracks all lock and unlock operations.

In the second task, we will then take a first step towards making your

Lock Tree algorithm applicable to real-world Java programs.

We will use a bytecode instrumentation library javassist to find all


locking operations in a Java application automatically.

In the third task, you will analyse a “real-world program” using the

algoirh

–>

Let’s Run It
I assume you pulled all changes from repository “tutors” and are now

inside folder a1_locktree .


Your folder structure should look like:

expected_test_outputs

lib

src

src_tests

build.xml

export_classpath.sh

run_ftp_test_X.sh

run_ftp_test_Y.sh
test_task1_single.sh

To compile the program, we provide ant configuration file

build.xml ,

which contains useful ant targets,


that allow you to compile our Java program:

ant compile (the default)

ant clean

Compile the program by calling ant (or ant compile ).


It will create folders

target/classes/src

target/classes/src_tests

with compiled .class files.

In the first task, we use executable tests—they contain method main —


so we directly execute them.

For example, look into class vt.locktree.test.task1.HelloWorld

(located src_tests/vt/locktree/test/task1/HelloWorld.java ).

The method main runs two threads, thread 1 and thread 2 , one
after another,

then prints lock trees, and checks whether there is a deadlock.

Execute:

ant compile
java -classpath ./target/classes/src:./target/classes/src

_tests/ \

vt.locktree.test.task1.HelloWorld

(the second and third lines describe one command,

where backslash allows me to separate the long command into two

lines)

This produces (excluding compilation messages):

Hello World!

Lock tree for thread ExampleThread 1

ExampleThread 1

Lock tree for thread ExampleThread 2

ExampleThread 2

checkTrees: implement me

No deadlocks found.

The pre-last line has checkTrees: implement me and this method you
will need to implement.
Note about -classpath
Note that in the above command we use argument -classpath to tell
Java where to find

vt.locktree.test.task1.HelloWorld (this is a full class name


including its package).

To avoid typing " -classpath ... " on every run,


you can set an environment variable as it is done in the script

export_classpath.sh .

Just call . export_classpath.sh (with the leading dot).

Now you can skip specifying -classpath and simply execute (in the
same terminal window!):

java vt.locktree.test.task1.HelloWorld

Task 1: Locktree Algorithm [50


points]
Implement the Locktree algorithm (Section 3.3.4.2 Deadlock detection

in the paper)

inside class vt.locktree.LockTreeChecker .

You will need to implement method checkTrees which currently looks


like this:

/**

* Analyse two trees and find all lock reversals in the t


rees.

* Take care of gate locks.

* Note that a pair of locks can appear more than once (s

ee e.g. test Ex008):

* This means that a pair appears reversed in two places.

* @return pairs of locks which appear reversed in tree1

and tree2.

*/

private List<LockPair> checkTrees(LockTree tree1, LockTre

e tree2) {

// TODO: implement me

System.out.println("checkTrees: implement me");

return new ArrayList<>();

Note that some pairs can appear more than once—this means that

a pair appears reversed in several places of the trees.

E.g., if you have trees:

T1 T2

| / \

6 4 4

| / \

4 6 6

then the pair (4,6) should appear twice in the resulting list.
Gate locks.
We use a slightly different notion of gate locks than what was given in
the lecture.
Given a pair of locks (l1, l2) that appear reversed in two trees,

l1-..-l2 in the first tree and l2-..-l1 in the second tree,

a gate lock is any lock, not equal to l1 nor l2 , which appears

above the node with l2 in the first tree and above the node with l1
in the second tree.

First example:

t1 t2

| | (2,3) is not DL: it is gated by 1

1 1 (there are no DLs)

| |

2 3

| |

3 2

Second example:

t1 t2

| | (2,3) is not DL: it is gated by 1

1 3 (1,3) is DL

| |

2 1

| |
3 2

Third example:

t1 t2

| | (1,2) is DL: 3 is not gating them

1 3 (2,3) is DL: 1 is not gating them

| | (1,3) is not DL: 2 is gating them

2 2

| |

3 1

Checking Task 1
The package vt.locktree.test.task1 (in the folder

src_tests/vt/locktree/test/task1 )

contains some tests that you can directly run using java .
The expected output for those tests is inside folder

expected_test_outputs/task1 .

We provide a script test_task1_single.sh that compiles, runs, and


compares the output.

Run it like ./test_task1_single.sh Basic001 ,

it the output differs, the script opens meld with the differing output.

For the final evaluation,

we will run a hundreds of tests and check your output with the correct

output.
Task 2: Instrumentation with
javassist [30 points]
In the previous task we used CustomLock to track lock and unlock
calls.

In this task, you will use javassist Java instrumentation library

to automatically insert necessary calls to our LockTreeChecker

whenever we see lock or unlock .

Look at class vt.locktree.Instrumenter .

The class’s main function takes a class-to-be-instrumented as a


parameter,

and then it should instrument the code of that class and inject calls:

1. inject a call to LockTreeChecker.lockCalled(...)

before any call to lockObj.lock()


2. inject a call to LockTreeChecker.unlockCalled(...)

after any call lockObj.unlockCalled(...)

In both cases, lockObj is either an instance of

java.util.concurrent.locks.ReentrantLock or
an instance of a class derived from

java.util.concurrent.locks.ReentrantLock .

For more details, read comments in vt.locktree.Instrumenter .

Testing Task 2
Let us look at the class vt.locktree.test.task2.HelloWorld (in

folder src_tests ).
You can run it directly by calling

java vt.locktree.test.task2.HelloWorld

and it will print Hello world! .


No injection was done so far.

Now if you call

java vt.locktree.LockTreeExecuter vt.locktree.test.task2.

HelloWorld

then the class LockTreeExecuter will automatically print Locktree


report

at the end of the execution, and you will get something like:

Hello World!

The program finished. Here is the report:

No deadlocks found.

Of course, no deadlocks are found, because no lock trees are built.

But if we instrument HelloWorld by calling

java vt.locktree.Instrumenter vt.locktree.test.task2.Hell


oWorld

and then call the previous command, then we will get something like

Hello World!

The program finished. Here is the report:

Lock tree for thread ExampleThread 1

ExampleThread 1

...ReentrantLock@6155e22[Unlocked] [HelloWorld.java: 15

...ReentrantLock@5e719166[Unlocked] [HelloWorld.java:

16]

Lock tree for thread ExampleThread 2

ExampleThread 2

...ReentrantLock@5e719166[Unlocked] [HelloWorld.java: 2

8]

...ReentrantLock@6155e22[Unlocked] [HelloWorld.java:

29]

Potential deadlocks in threads: (ExampleThread 1, Example

Thread 2)

The locks are:

(java.util.concurrent.locks.ReentrantLock@5e719166[Unlock

ed],

java.util.concurrent.locks.ReentrantLock@6155e22[Unlocke

d])
For more details, see class Instrumenter and LockTreeExecuter

(and call them with -h ).

(Hint: how to check if your call was instrumented or not?

I use IDE IntelliJ and when double-click on the class file—it then

decompiles it

and then I can see whether the call was injected or not.)

Let us note two main mistakes of students of the previous years.

The first mistake is to intercept calls to all methods named lock and

unlock ,

without checking if the object is related to ReentrantLock .

(Example: my class has a method lock ,

but the class does not relate to ReentrantLock in any way)


The second mistake is to instrument methods, but forget to instrument

constructors.

As in task 2, in the final evaluation we run tests and check your output

with the correct output.

Task 3: analyse FTP server [20


points]
We have two subtasks.

Task 3.1: run_ftp_test_X.sh [10


points]
Look into script run_ftp_test_X.sh .
The script runs the server, then creates two clients that connect

and send some commands to the server.

Run the script the analyse the result.

1. Create file ftp_test_X_short_answer.txt (inside the folder

a1_locktree ) and put there your answers to the following


questions:

(YES/NO):

Does Locktree algorithm report at least one real

deadlock or all reported deadlocks are spurious?

Write YES or NO into the first line of

ftp_test_X_short_answer.txt

If YES, where the deadlock happens?

Put names of two methods, where the deadlock

happens,

one method name per line (without class name or line

numbers, just method name).

Thus, ftp_test_X_short_answer.txt either contains three


lines or a single line.

2. Create file ftp_test_X_long_answer.txt and write there the

explanation,

in English, why the deadlock is spurious or real—in particularly,


describe the events that lead to a deadlock.

It could look like this:

main Thread-1 Thread-2

client-1 connects

creates Thread-1

starts execution

client-2 conn

ects

If the deadlock is spurious, write in this file the explanation.

Task 3.2: run_ftp_test_Y.sh [10


points]
Look into script run_ftp_test_Y.sh .
The script runs the server, then creates one client that connects

and sends some commands to the server.

Run the script the analyse the result.

Create two files, ftp_test_Y_short_answer.txt and

ftp_test_Y_long_answer.txt ,
and proceed answering the same questions as in the previous task.

Literature
W. Visser, K. Havelund, G. Brat, S. Park and F. Lerda, Model Checking

Programs, International Journal on Automated Software Engineering


10(2), April 2003. Extended journal version of paper presented at the

ASE’00 conference

Você também pode gostar