Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

Assignment 1: Lock Tree Algorithm

Ayrat Khalimov, 2017

Type: individual work


Purpose: Understand the Lock Tree Algorithm.
Task: Implement the Lock Tree Algorithm in Java.
Deadline: Nov 9 (23:59 Graz timezone), 2017.
(Technically, you can push changes after the deadline, but they will be ignored)

System Setup
We will test your code in the following setup:
• Ubuntu 16.04
• java version “9” (oracle)

Git Setup
The repository for all material is here:
https://extgit.iaik.tugraz.at/scos/vt2017
You have a read-access to it.
For this assignment, you we will create a git repository for you, and send you
the credentials. Once you get the credentials, call:
git clone <your_repository_url> vt_project1
This will clone an empty repository inside folder vt_project1. Go inside it and
add our repository with all the material.
git remote add tutors https://extgit.iaik.tugraz.at/scos/vt2017
And now you can pull from it by calling:
git pull tutors master

1
This command will merge all updates from repository tutors into your repository.
Now your repository should contain folder a1_locktree that has all the code
that we provide. You work inside that folder and modify those files directly.
Deliverable When you are done with the assignment, do tag it and push it by
calling
git push
git tag assignment1
git push origin --tags
This command will upload all your changes into your repository, and tag them
for testing.

Intro
In this assignment, you will implement the Locktree algorithm in Java. The
assignment has three tasks:
1. Implement Locktree algorithm that uses CustomLock
2. javassist: implement Instrumenter that tracks calls to lock() and
unlock().
3. Using your Instrumenter and our LockTreeExecuter, analyse deadlocks
in our FTP server.

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

2
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 di-
rectly 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
1
2

Lock tree for thread ExampleThread 2


ExampleThread 2
2
1

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

3
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 trees.
* Take care of gate locks.
* Note that a pair of locks can appear more than once (see 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, LockTree 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

4
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(...)

5
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.HelloWorld
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: 28]
...ReentrantLock@6155e22[Unlocked] [HelloWorld.java: 29]

Potential deadlocks in threads: (ExampleThread 1, ExampleThread 2)


The locks are:
(java.util.concurrent.locks.ReentrantLock@5e719166[Unlocked],
java.util.concurrent.locks.ReentrantLock@6155e22[Unlocked])
For more details, see class Instrumenter and LockTreeExecuter (and call them
with -h).

6
(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 connects
If the deadlock is spurious, write in this file the explanation.

7
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

You might also like