Closed GoogleCodeExporter closed 9 years ago
Hi,
The stack overflow is not nice, however without test case it will be hard to
find the
reason. But after the stack overflow there is a deadlock detected:
Session #10 (user: DIRECTOR) is waiting to lock PUBLIC.GGS_OBJECTS while
locking PUBLIC.MPS_HISTORY (exclusive), PUBLIC.MPS (exclusive).
Session #6 (user: DIRECTOR) is waiting to lock PUBLIC.MPS while locking
PUBLIC.GGS_OBJECTS (exclusive). [40001-107]
Is this the wrong deadlock?
Original comment by thomas.t...@gmail.com
on 11 Feb 2009 at 7:12
Yes, the right deadlock is detected, I am just concerning that the stack
overflow
makes it harder to debug.
Anyways, after debugging it on Eclipse, it looks that the stack overflow is
caused by
this piece of code:
if (error == null && lockExclusive != null) {
Table t = lockExclusive.getWaitForLock();
if (t != null) {
error = t.checkDeadlock(lockExclusive, clash);
if (error != null) {
error.add(session);
}
}
"this" refers to a table called MPS and t is table GGS_OBJECTS; when
t.checkDeadlock() is called, "this" is GGS_OBJECTS and t is MPS, and so on...
Original comment by felip...@gmail.com
on 11 Feb 2009 at 7:42
Here is another update, now including the session lock information
1.call is made to OBJ.checkDeadLock(5, 6) (OBJ is table, 5 and 6 are sessions)
2.in that method, this.lockExclusive == MPS, and MPS.getWaitForLock() == 8,
which
causes call to:
3.MPS.checkDeadlock(8, 6)
4.in that method, this.lockExclusive == OBJS, and OBJS.getWaitForLock() == 5,
which
causes call to 1
So, it looks like checking only for session == clash is not enough to find a
circle.
Original comment by felip...@gmail.com
on 11 Feb 2009 at 8:21
Ok, found a solution: change the clash parameter to be a Set.
If I change it to:
public ObjectArray checkDeadlock(Session session, Set clash) {
// only one deadlock check at any given time
synchronized (TableData.class) {
if (clash == null) {
// verification is started
clash = new HashSet();
} else if (clash.contains(session)) {
// we found a circle
return new ObjectArray();
}
clash.add(session);
Then I don't get the stack overflow anymore.
If you think this solution is fine (the only drawback would be the increased
performance, as it would be creating Set instances), I could try to add a test
case
and patch.
Original comment by felip...@gmail.com
on 11 Feb 2009 at 9:19
Ok, here is a patch, test case included (if you run it without the change, you
will
get a StackOverflow).
I also included a trace call before a lock is acquired (I think it can help
detecting
dead locks, but feel free to remove such call).
Original comment by felip...@gmail.com
on 11 Feb 2009 at 10:10
Attachments:
BTW, the 'deadlick' was a typo, it wasn't intentional. But it looks like I can't
change the title once it was submitted...
Original comment by felip...@gmail.com
on 12 Feb 2009 at 5:35
Original comment by thomas.t...@gmail.com
on 12 Feb 2009 at 6:22
Hi Thomas,
Were you able to reproduce this problem? What about the proposed fix?
Sorry for pushing these questions, but I'm currently using the patched H2 and
was
wondering if such change would eventually make it.
-- Felipe
Original comment by felip...@gmail.com
on 17 Feb 2009 at 8:55
Hi,
Sorry for the delay. I'm still trying to create a test case for this problem.
Once I have that I will fix it.
Original comment by thomas.t...@gmail.com
on 3 Apr 2009 at 12:50
Hi Thomas,
I already created a test case, it's available in the patch I provided
(http://h2database.googlecode.com/issues/attachment?aid=5336640199476198141&name
=H2-Issue61.patch).
-- Felipe
Original comment by felip...@gmail.com
on 3 Apr 2009 at 2:15
I'm sorry... I will test it.
Original comment by thomas.t...@gmail.com
on 3 Apr 2009 at 4:00
Hi,
I'm sorry for the delay! I understand the problem now, and why it was not
working. I
just write it down here so I can look it up later if required:
Circular locks were detected (C1 locks A, C2 locks B, C3 locks C). However not
this:
C1 and C2 are deadlocked (which is detected later but too late), C3 tries to
lock a
table of C1 or C2. In that case, the deadlock check of C3 is an endless
recursion.
The test case is (all exclusive locks, + successful, ? tries)
C1 C2 C3
========
A+
B+ C+
B?
A?
C?
The only problem with your test case is that sometimes two deadlocks are
detected (C1
and C3 I believe). That's normal in this test case, so I have to change
checkDeadlock
to allow 2 exception in that case.
Anyway, I will apply your patch, it will be included in the next release.
Thanks a lot for your help and your patience!
Original comment by thomas.t...@gmail.com
on 4 Apr 2009 at 7:32
I found a problem with your patch. As I wrote sometimes two deadlocks are
detected.
This shouldn't be the case. The solution is to pass both the visited (HashSet)
and
the clash (Session). Do not recurse when already visited, but only throw when
part of
the circle.
Original comment by thomas.t...@gmail.com
on 5 Apr 2009 at 9:36
Hi Thomas,
Please feel free to improve it; unfortunately, I won't be able to help you
these days
(for lack of time :-(.
-- Felipe
Original comment by felip...@gmail.com
on 5 Apr 2009 at 7:32
Fixed in version 1.1.111 (2009-04-10)
Original comment by thomas.t...@gmail.com
on 10 Apr 2009 at 8:23
Original issue reported on code.google.com by
felip...@gmail.com
on 11 Feb 2009 at 4:58