Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement deadlock analysis and extend with MHP #655

Merged
merged 32 commits into from
Mar 25, 2022
Merged

Reimplement deadlock analysis and extend with MHP #655

merged 32 commits into from
Mar 25, 2022

Conversation

sim642
Copy link
Member

@sim642 sim642 commented Mar 21, 2022

The refactoring of deadlock analysis for #650 turned into an almost complete rewrite. Extending with common lockset and MHP information was very straightforward.

Changes

  1. Use split global constraint unknowns for recording locking orders instead of a global OCaml variable.
  2. Replace transitive locking order shortcutting on addition with a locking order graph search (DFS) at the end. This is more flexible and wastes less memory by not actually storing all the edges of the transitive closure.
  3. Replace Cil.location with Node for locking events. This makes it incrementally more stable.
  4. Improve readability of deadlock warnings by outputting the entire locking order cycle in a grouped message. Previously the transitive shortcutting made cycles longer than 2 difficult to interpret, because intermediate mutexes and locations were omitted.
  5. Add Deadlock message category.
  6. Exclude deadlocks by access information, which is independent of memory location (common lockset, MHP).

This is directly on master, but I will take care of the merge into #391 when this lands. I already know that will require a few changes to adapt this to #634, which is only on interactive).

Example

Here's how ./regtest.sh 15 03 outputs the three-mutex locking cycle:

[Warning][Deadlock] Locking order cycle:
  lock before: mutex2 with [mhp:{tid=[main, t2@tests/regression/15-deadlock/03-triple_deadlock.c:42:5-42:40]}, thread:[main, t2@tests/regression/15-deadlock/03-triple_deadlock.c:42:5-42:40]] (tests/regression/15-deadlock/03-triple_deadlock.c:20:3-20:30)
  lock after: mutex3 with [mhp:{tid=[main, t2@tests/regression/15-deadlock/03-triple_deadlock.c:42:5-42:40]}, lock:{mutex2}, thread:[main, t2@tests/regression/15-deadlock/03-triple_deadlock.c:42:5-42:40]] (tests/regression/15-deadlock/03-triple_deadlock.c:21:3-21:30)
  lock before: mutex3 with mhp:{tid=[main], {t3@tests/regression/15-deadlock/03-triple_deadlock.c:43:5-43:40}} (tests/regression/15-deadlock/03-triple_deadlock.c:29:3-29:30)
  lock after: mutex1 with [mhp:{tid=[main], {t3@tests/regression/15-deadlock/03-triple_deadlock.c:43:5-43:40}}, lock:{mutex3}] (tests/regression/15-deadlock/03-triple_deadlock.c:30:3-30:30)
  lock before: mutex1 with mhp:{tid=[main], {t1@tests/regression/15-deadlock/03-triple_deadlock.c:41:5-41:40}} (tests/regression/15-deadlock/03-triple_deadlock.c:11:3-11:30)
  lock after: mutex2 with [mhp:{tid=[main], {t1@tests/regression/15-deadlock/03-triple_deadlock.c:41:5-41:40}}, lock:{mutex1}] (tests/regression/15-deadlock/03-triple_deadlock.c:12:3-12:30)

@sim642 sim642 added the cleanup Refactoring, clean-up label Mar 21, 2022
@sim642 sim642 added this to the v2.0.0 milestone Mar 21, 2022
@michael-schwarz
Copy link
Member

Also, I think we now get to the point, where we can probably not just ignore double locking anymore. While it may be undefinied behavior in pthreads, I think double locking a mutex that is not configured to support it, also constitutes a deadlock in some philosophical sense, right?

Otherwise no Lock/Unlock events get emitted.
@sim642
Copy link
Member Author

sim642 commented Mar 22, 2022

Also, I think we now get to the point, where we can probably not just ignore double locking anymore. While it may be undefinied behavior in pthreads, I think double locking a mutex that is not configured to support it, also constitutes a deadlock in some philosophical sense, right?

That's a good point indeed, especially since recursive mutexes don't self-deadlock (although for the new privatizations we assume they do AFAIK). That should probably be addressed separately too, to have tracking of mutex types and then we could relatively easily simply even warn about that default undefined behavior. This is related to #176.

@michael-schwarz
Copy link
Member

although for the new privatizations we assume they do AFAIK

No, iirc we simply assume all mutexes are recursive in the implementation, and in the paper we don't deal with them at all.

@sim642 sim642 linked an issue Mar 22, 2022 that may be closed by this pull request
4 tasks
@sim642
Copy link
Member Author

sim642 commented Mar 22, 2022

Turns out our framework is so great that adding common lockset and MHP information to locking events to exclude some deadlocks was very straightforward, so I added that into this PR. With our existing mutex, mhp and threadJoins analyses, we can deal with the example from here: https://arxiv.org/abs/1607.06927 (also added as regression test).

@sim642 sim642 changed the title Reimplement deadlock analysis Reimplement deadlock analysis and extend with MHP Mar 22, 2022
@michael-schwarz
Copy link
Member

I am still adding some examples and checking some smaller things. When I'm done with that (hopefully later today), I'd be cool with merging it and then fixing the issues with Must vs May locks in #662 as you suggested.

@michael-schwarz
Copy link
Member

I think the most problematic issue we still have here is threads that end while holding locks. Any future attempt to acquire that lock may result in a deadlock. (Not sure if this is a deadlock according to some definitions that require each thread to be waiting on a resource, but I still think this something we should attempt to catch, maybe we could do it an a separate PR though).


Also, I wasted a lot of time trying to come up with an example where one has a deadlock despite not all locking operations pairwise may-happen-in parallel, which turns out was a waste of time.
In the process, I found a (maybe questionable) enhancement of MHP: P1 and P2 may not happen in parallel, if some thread is must-joined at P1 but definitely not created at P2. I now added it and an example for it to this PR, but we can of course also move that to somewhere else.

type access =
| Memory of memory_access (** Memory location access (race). *)
| Point (** Program point and state access (MHP), independent of memory location. *)
[@@deriving ord, hash] (* TODO: fix ppx_deriving_hash on variant with inline record *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you already fixed this in ppx_deriving_hash by now, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, but I didn't yet make a new release just for that nor add an opam pin to Goblint to annoy everyone. There's no downside to having a separate named record type here, so I'd just leave it as is for now and change in sometime in the future.

Copy link
Member

@michael-schwarz michael-schwarz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think how easy it was to enhance this with MHP information is a good sign we went for the right design here, and as always, I'm impressed with the speed with which you implemented this Simmo!

@michael-schwarz
Copy link
Member

Not sure if we want to solve the issue with threads ending while holding mutexes here or make a new issue and PR for it?

@sim642
Copy link
Member Author

sim642 commented Mar 25, 2022

Not sure if we want to solve the issue with threads ending while holding mutexes here or make a new issue and PR for it?

I think we should SKIP it here and have a separate issue, because that's a somewhat different form of a deadlock. It's not just about locking order any more.

@sim642
Copy link
Member Author

sim642 commented Mar 25, 2022

In the process, I found a (maybe questionable) enhancement of MHP: P1 and P2 may not happen in parallel, if some thread is must-joined at P1 but definitely not created at P2. I now added it and an example for it to this PR, but we can of course also move that to somewhere else.

This is the reason why 15-deadlock-mhp2 doesn't have a deadlock, right? It had no annotations, so I added them, hopefully correctly.

@michael-schwarz
Copy link
Member

This is the reason why 15-deadlock-mhp2 doesn't have a deadlock, right?

Yes!

@sim642 sim642 merged commit e7121bf into master Mar 25, 2022
@sim642 sim642 deleted the deadlock branch March 25, 2022 16:50
sim642 added a commit to sim642/opam-repository that referenced this pull request Aug 18, 2022
CHANGES:

Goblint "lean" release after a lot of cleanup.

* Remove unmaintained analyses: OSEK, ARINC, shapes, containment, deadlocksByRaces (goblint/analyzer#460, goblint/analyzer#736, goblint/analyzer#812, goblint/analyzer#474).
* Add interactive analysis (goblint/analyzer#391).
* Add server mode (goblint/analyzer#522).
* Add Compilation Database support (goblint/analyzer#406, goblint/analyzer#448).
* Add floating point domain, unrolled array domain and improved struct domains (goblint/analyzer#734, goblint/analyzer#761, goblint/analyzer#577, goblint/analyzer#419).
* Add static loop unrolling and heap variable unrolling (goblint/analyzer#563, goblint/analyzer#722).
* Improve race detection with may-happen-in-parallel analysis (goblint/analyzer#529, goblint/analyzer#518, goblint/analyzer#595).
* Reimplement lockset and deadlock analyses (goblint/analyzer#659, goblint/analyzer#662, goblint/analyzer#650, goblint/analyzer#655).
* Add pthread extraction to Promela (goblint/analyzer#220).
* Add location spans to output (goblint/analyzer#428, goblint/analyzer#449).
* Improve race reporting (goblint/analyzer#550, goblint/analyzer#551).
* Improve dead code reporting (goblint/analyzer#94, goblint/analyzer#353, goblint/analyzer#785).
* Refactor warnings (goblint/analyzer#55, goblint/analyzer#783).
* Add JSON schema for configuration (goblint/analyzer#476, goblint/analyzer#499).
* Refactor option names (goblint/analyzer#28, goblint/analyzer#192, goblint/analyzer#516, goblint/analyzer#675).
* Add bash completion (goblint/analyzer#669).
* Add OCaml 4.13 and 4.14 support, remove OCaml 4.09 support (goblint/analyzer#503, goblint/analyzer#672).
sim642 added a commit to sim642/opam-repository that referenced this pull request Aug 18, 2022
CHANGES:

Goblint "lean" release after a lot of cleanup.

* Remove unmaintained analyses: OSEK, ARINC, shapes, containment, deadlocksByRaces (goblint/analyzer#460, goblint/analyzer#736, goblint/analyzer#812, goblint/analyzer#474).
* Add interactive analysis (goblint/analyzer#391).
* Add server mode (goblint/analyzer#522).
* Add Compilation Database support (goblint/analyzer#406, goblint/analyzer#448).
* Add floating point domain, unrolled array domain and improved struct domains (goblint/analyzer#734, goblint/analyzer#761, goblint/analyzer#577, goblint/analyzer#419).
* Add static loop unrolling and heap variable unrolling (goblint/analyzer#563, goblint/analyzer#722).
* Improve race detection with may-happen-in-parallel analysis (goblint/analyzer#529, goblint/analyzer#518, goblint/analyzer#595).
* Reimplement lockset and deadlock analyses (goblint/analyzer#659, goblint/analyzer#662, goblint/analyzer#650, goblint/analyzer#655).
* Add pthread extraction to Promela (goblint/analyzer#220).
* Add location spans to output (goblint/analyzer#428, goblint/analyzer#449).
* Improve race reporting (goblint/analyzer#550, goblint/analyzer#551).
* Improve dead code reporting (goblint/analyzer#94, goblint/analyzer#353, goblint/analyzer#785).
* Refactor warnings (goblint/analyzer#55, goblint/analyzer#783).
* Add JSON schema for configuration (goblint/analyzer#476, goblint/analyzer#499).
* Refactor option names (goblint/analyzer#28, goblint/analyzer#192, goblint/analyzer#516, goblint/analyzer#675).
* Add bash completion (goblint/analyzer#669).
* Add OCaml 4.13 and 4.14 support, remove OCaml 4.09 support (goblint/analyzer#503, goblint/analyzer#672).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cleanup Refactoring, clean-up
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Revamp Deadlock-Detection to work incrementally and consider MHP information
2 participants