Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-20 Thread Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL282011: [analyzer] Add a checker that detects blocks in 
critical sections (authored by zaks).

Changed prior to commit:
  https://reviews.llvm.org/D21506?vs=71375=71977#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D21506

Files:
  cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
  cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
  cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
  cfe/trunk/test/Analysis/block-in-critical-section.cpp

Index: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
===
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -436,6 +436,10 @@
   HelpText<"Check for misuses of stream APIs">,
   DescFile<"SimpleStreamChecker.cpp">;
 
+def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
+  HelpText<"Check for calls to blocking functions inside a critical section">,
+  DescFile<"BlockInCriticalSectionChecker.cpp">;
+
 } // end "alpha.unix"
 
 let ParentPackage = CString in {
Index: cfe/trunk/test/Analysis/block-in-critical-section.cpp
===
--- cfe/trunk/test/Analysis/block-in-critical-section.cpp
+++ cfe/trunk/test/Analysis/block-in-critical-section.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
+
+void sleep(int x) {}
+
+namespace std {
+struct mutex {
+  void lock() {}
+  void unlock() {}
+};
+}
+
+void testBlockInCriticalSection() {
+  std::mutex m;
+  m.lock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  m.unlock();
+}
+
+void testBlockInCriticalSectionWithNestedMutexes() {
+  std::mutex m, n, k;
+  m.lock();
+  n.lock();
+  k.lock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  k.unlock();
+  sleep(5); // expected-warning {{A blocking function %s is called inside a critical section}}
+  n.unlock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  m.unlock();
+  sleep(3); // no-warning
+}
+
+void f() {
+  sleep(1000); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
+
+void testBlockInCriticalSectionInterProcedural() {
+  std::mutex m;
+  m.lock();
+  f();
+  m.unlock();
+}
+
+void testBlockInCriticalSectionUnexpectedUnlock() {
+  std::mutex m;
+  m.unlock();
+  sleep(1); // no-warning
+  m.lock();
+  sleep(1); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
Index: cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -0,0 +1,109 @@
+//===-- BlockInCriticalSectionChecker.cpp ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// Defines a checker for blocks in critical sections. This checker should find
+// the calls to blocking functions (for example: sleep, getc, fgets, read,
+// recv etc.) inside a critical section. When sleep(x) is called while a mutex
+// is held, other threades cannot lock the same mutex. This might take some
+// time, leading to bad performance or even deadlock.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class BlockInCriticalSectionChecker : public Checker {
+
+  CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn;
+
+  std::unique_ptr BlockInCritSectionBugType;
+
+  void reportBlockInCritSection(SymbolRef FileDescSym,
+const CallEvent ,
+CheckerContext ) const;
+
+public:
+  BlockInCriticalSectionChecker();
+
+  void checkPreCall(const CallEvent , CheckerContext ) const;
+
+  /// Process unlock.
+  /// Process lock.
+  /// Process blocking functions (sleep, getc, fgets, read, recv)
+  void checkPostCall(const CallEvent , CheckerContext ) const;
+
+};

Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-19 Thread Anna Zaks via cfe-commits
zaks.anna added a comment.

This checker is now in alpha.unix, because it is new and is in active 
development. However, alpha checkers are not supported and are not turned on by 
default, so we should move it into unix package once we think it is ready to be 
used.

Evaluation on a large real codebase (or several) would give us a higher 
confidence in the checker, so it will be valuable to perform that before we 
move the package out of alpha. However, clang is probably not a good codebase 
to test this on because it's not heavily multithreaded.


Repository:
  rL LLVM

https://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-18 Thread Zoltán Dániel Török via cfe-commits
zdtorok added a comment.

As it's my first contribution I think I have no commit access.
So far I could not test it on larger codebase. I've tried to do so on clang but 
my computer was too slow for that. I will try it again.
What you mean by alpha-phase? What should be the next steps now?


Repository:
  rL LLVM

https://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-14 Thread Anna Zaks via cfe-commits
zaks.anna accepted this revision.
zaks.anna added a comment.
This revision is now accepted and ready to land.

LGTM! Thanks!

Future steps:
How do we plan to bring this checker out of alpha? Have you evaluated it on 
large codebases?


Repository:
  rL LLVM

https://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-14 Thread Zoltán Dániel Török via cfe-commits
zdtorok added a comment.

You are right NoQ, thank you for the remark, I've upload a new diff containing 
a fix for the integer underflow case.


Repository:
  rL LLVM

https://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-14 Thread Zoltán Dániel Török via cfe-commits
zdtorok updated this revision to Diff 71375.
zdtorok added a comment.
Herald added subscribers: mgorny, beanz.

Fixed possible integer-underflow in case of unexpected unlocking function. Also 
added test for this.


Repository:
  rL LLVM

https://reviews.llvm.org/D21506

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  test/Analysis/block-in-critical-section.cpp

Index: test/Analysis/block-in-critical-section.cpp
===
--- /dev/null
+++ test/Analysis/block-in-critical-section.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
+
+void sleep(int x) {}
+
+namespace std {
+struct mutex {
+  void lock() {}
+  void unlock() {}
+};
+}
+
+void testBlockInCriticalSection() {
+  std::mutex m;
+  m.lock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  m.unlock();
+}
+
+void testBlockInCriticalSectionWithNestedMutexes() {
+  std::mutex m, n, k;
+  m.lock();
+  n.lock();
+  k.lock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  k.unlock();
+  sleep(5); // expected-warning {{A blocking function %s is called inside a critical section}}
+  n.unlock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  m.unlock();
+  sleep(3); // no-warning
+}
+
+void f() {
+  sleep(1000); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
+
+void testBlockInCriticalSectionInterProcedural() {
+  std::mutex m;
+  m.lock();
+  f();
+  m.unlock();
+}
+
+void testBlockInCriticalSectionUnexpectedUnlock() {
+  std::mutex m;
+  m.unlock();
+  sleep(1); // no-warning
+  m.lock();
+  sleep(1); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -9,6 +9,7 @@
   ArrayBoundChecker.cpp
   ArrayBoundCheckerV2.cpp
   BasicObjCFoundationChecks.cpp
+  BlockInCriticalSectionChecker.cpp
   BoolAssignmentChecker.cpp
   BuiltinFunctionChecker.cpp
   CStringChecker.cpp
Index: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -0,0 +1,109 @@
+//===-- BlockInCriticalSectionChecker.cpp ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// Defines a checker for blocks in critical sections. This checker should find
+// the calls to blocking functions (for example: sleep, getc, fgets, read,
+// recv etc.) inside a critical section. When sleep(x) is called while a mutex
+// is held, other threades cannot lock the same mutex. This might take some
+// time, leading to bad performance or even deadlock.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class BlockInCriticalSectionChecker : public Checker {
+
+  CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn;
+
+  std::unique_ptr BlockInCritSectionBugType;
+
+  void reportBlockInCritSection(SymbolRef FileDescSym,
+const CallEvent ,
+CheckerContext ) const;
+
+public:
+  BlockInCriticalSectionChecker();
+
+  void checkPreCall(const CallEvent , CheckerContext ) const;
+
+  /// Process unlock.
+  /// Process lock.
+  /// Process blocking functions (sleep, getc, fgets, read, recv)
+  void checkPostCall(const CallEvent , CheckerContext ) const;
+
+};
+
+} // end anonymous namespace
+
+REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
+
+BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
+: LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
+  FgetsFn("fgets"), ReadFn("read"), RecvFn("recv") {
+  // Initialize the bug type.
+  BlockInCritSectionBugType.reset(
+  new BugType(this, "Call to blocking function in critical section",
+   

Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-12 Thread Artem Dergachev via cfe-commits
NoQ added a comment.

I think there's still this problem i've outlined in the comment above: you can 
step into an integer-underflow if your analysis begins with unlock(). You could 
just ignore all unlocks that move you below 0, which would be ok.

Could you add this test?

  std::mutex m;
  void foo() {
m.unlock(); // MutexCount = 4294967295, should be 0, just ignore this 
unlock.
sleep(1); // no-warning
m.lock(); // MutexCount = 0, should be 1, woohoo we're sure we're in the 
section now.
// What's the current mutex count?
sleep(1); // expected-warning{{}}
  }


Repository:
  rL LLVM

https://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21506: [analyzer] Block in critical section

2016-09-05 Thread Zoltán Dániel Török via cfe-commits
zdtorok removed rL LLVM as the repository for this revision.
zdtorok updated this revision to Diff 70345.
zdtorok marked an inline comment as done.
zdtorok added a comment.

Fixed based on the provided comments and feedbacks.

- added new inter-procedural tests
- minor styling fix (trailing whitespaces)
- fixed tests (missing verify option)
- fixed post, preCall checks


https://reviews.llvm.org/D21506

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  test/Analysis/block-in-critical-section.cpp

Index: test/Analysis/block-in-critical-section.cpp
===
--- /dev/null
+++ test/Analysis/block-in-critical-section.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s
+
+void sleep(int x) {}
+
+namespace std {
+struct mutex {
+  void lock() {}
+  void unlock() {}
+};
+}
+
+void testBlockInCriticalSection() {
+  std::mutex m;
+  m.lock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  m.unlock();
+}
+
+void testBlockInCriticalSectionWithNestedMutexes() {
+  std::mutex m, n, k;
+  m.lock();
+  n.lock();
+  k.lock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  k.unlock();
+  sleep(5); // expected-warning {{A blocking function %s is called inside a critical section}}
+  n.unlock();
+  sleep(3); // expected-warning {{A blocking function %s is called inside a critical section}}
+  m.unlock();
+  sleep(3); // no-warning
+}
+
+void f() {
+  sleep(1000); // expected-warning {{A blocking function %s is called inside a critical section}}
+}
+
+void testBlockInCriticalSectionInterProcedural() {
+  std::mutex m;
+  m.lock();
+  f();
+  m.unlock();
+}
Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -9,6 +9,7 @@
   ArrayBoundChecker.cpp
   ArrayBoundCheckerV2.cpp
   BasicObjCFoundationChecks.cpp
+  BlockInCriticalSectionChecker.cpp
   BoolAssignmentChecker.cpp
   BuiltinFunctionChecker.cpp
   CStringChecker.cpp
Index: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -0,0 +1,109 @@
+//===-- BlockInCriticalSectionChecker.cpp ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// Defines a checker for blocks in critical sections. This checker should find
+// the calls to blocking functions (for example: sleep, getc, fgets, read,
+// recv etc.) inside a critical section. When sleep(x) is called while a mutex
+// is held, other threades cannot lock the same mutex. This might take some
+// time, leading to bad performance or even deadlock.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class BlockInCriticalSectionChecker : public Checker {
+
+  CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn;
+
+  std::unique_ptr BlockInCritSectionBugType;
+
+  void reportBlockInCritSection(SymbolRef FileDescSym,
+const CallEvent ,
+CheckerContext ) const;
+
+public:
+  BlockInCriticalSectionChecker();
+
+  void checkPreCall(const CallEvent , CheckerContext ) const;
+
+  /// Process unlock.
+  /// Process lock.
+  /// Process blocking functions (sleep, getc, fgets, read, recv)
+  void checkPostCall(const CallEvent , CheckerContext ) const;
+
+};
+
+} // end anonymous namespace
+
+REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned)
+
+BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
+: LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
+  FgetsFn("fgets"), ReadFn("read"), RecvFn("recv") {
+  // Initialize the bug type.
+  BlockInCritSectionBugType.reset(
+  new BugType(this, "Call to blocking function in critical section",
+"Blocking Error"));
+}
+
+void 

Re: [PATCH] D21506: [analyzer] Block in critical section

2016-06-20 Thread Anna Zaks via cfe-commits
zaks.anna added a comment.

Thanks for the patch!

Have you run this on a large codebase?



Comment at: include/clang/StaticAnalyzer/Checkers/Checkers.td:406
@@ +405,3 @@
+def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
+  HelpText<"Check for blocks in critical section">,
+  DescFile<"BlockInCriticalSectionChecker.cpp">;

"blocks" sounds a lot like blocks ObjC feature. I'd just be more explicit and 
say "Check for calls to blocking functions inside a critical section".

Please, change the name of the class as well.


Comment at: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp:54
@@ +53,3 @@
+
+REGISTER_TRAIT_WITH_PROGRAMSTATE(Counter, unsigned)
+

Counter -> MutexCounter or MutexState


Comment at: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp:61
@@ +60,3 @@
+  BlockInCritSectionBugType.reset(
+  new BugType(this, "Block in critical section", "Unix Stream API Error"));
+}

Same here: "Block" sounds like an ObjC language feature. Also, the category 
name ("Unix Stream API Error") should be different.


Comment at: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp:85
@@ +84,3 @@
+
+void BlockInCriticalSectionChecker::checkPreCall(const CallEvent ,
+ CheckerContext ) const {

Why is handling of unlock in preCall?


Comment at: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp:96
@@ +95,3 @@
+
+void BlockInCriticalSectionChecker::reportBlockInCritSection(
+SymbolRef BlockDescSym, const CallEvent , CheckerContext ) const {

It would be great if you could implement a BugReporterVisitor that walks the 
path and explains where the lock has occurred. (This is not blocking for this 
commit.)


Comment at: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp:103
@@ +102,3 @@
+  auto R = llvm::make_unique(*BlockInCritSectionBugType,
+  "Block in a critical section", ErrNode);
+  R->addRange(Call.getSourceRange());

 "Block in a critical section" -> "A blocking function %s is called inside a 
critical section."


Comment at: test/Analysis/block-in-critical-section.cpp:12
@@ +11,3 @@
+
+void testBlockInCriticalSection() {
+  std::mutex m;

Please, add inter-procedural examples like in the description of the checker.


Repository:
  rL LLVM

http://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D21506: [analyzer] Block in critical section

2016-06-20 Thread Artem Dergachev via cfe-commits
NoQ added a comment.

Useful stuff!

When I see your approach with `mutexCount`, the following test case comes to 
mind:

  std::mutex m;
  void foo() {
// Suppose this function is always called
// with the mutex 'm' locked.
m.unlock();
// Here probably some useful work is done.
m.lock();
// What's the current mutex count?
sleep(1); // expected-warning{{}}
  }



Comment at: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp:11
@@ +10,3 @@
+// Defines a checker for blocks in critical sections. This checker should find 
+// the calls to blocking functions (for example: sleep, getc, fgets, read, 
+// recv etc.) inside a critical section. When sleep(x) is called while a mutex

A bit of trailing whitespace here.


Comment at: test/Analysis/block-in-critical-section.cpp:1
@@ +1,2 @@
+// RUN: %clang --analyze -std=c++11 -Xclang -analyzer-checker -Xclang 
alpha.unix.BlockInCriticalSection %s
+

The run line is lacking `-verify`, and therefore these tests always pass. In 
your case, it'd be `-Xclang -verify`. On the other hand, i'm not sure if it's a 
good idea to run the test under the driver, instead of the standard `-cc1` 
approach - after all, you aren't including any system headers in the test.


Repository:
  rL LLVM

http://reviews.llvm.org/D21506



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D21506: [analyzer] Block in critical section

2016-06-19 Thread Zoltán Dániel Török via cfe-commits
zdtorok created this revision.
zdtorok added reviewers: zaks.anna, dcoughlin, xazax.hun.
zdtorok added a subscriber: cfe-commits.
zdtorok set the repository for this revision to rL LLVM.

This checker should find the calls to blocking functions (for example: sleep, 
getc, fgets,read,recv etc.) inside a critical section. When sleep(x) is called 
while a mutex is held, other threads cannot lock the same mutex. This might 
take some time, leading to bad performance or even deadlock.

Example:

```
mutex_t m;

void f() {
  sleep(1000); // Error: sleep() while m is locked! [f() is called from 
foobar() while m is locked]
  // do some work
}

void foobar() {
  lock(m);
  f();
  unlock(m);
}
```

Repository:
  rL LLVM

http://reviews.llvm.org/D21506

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  test/Analysis/block-in-critical-section.cpp

Index: test/Analysis/block-in-critical-section.cpp
===
--- /dev/null
+++ test/Analysis/block-in-critical-section.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang --analyze -std=c++11 -Xclang -analyzer-checker -Xclang alpha.unix.BlockInCriticalSection %s
+
+void sleep(int x) {}
+
+namespace std {
+struct mutex {
+  void lock() {}
+  void unlock() {}
+};
+}
+
+void testBlockInCriticalSection() {
+  std::mutex m;
+  m.lock();
+  sleep(3); // expected-warning {{Block in a critical section}}
+  m.unlock();
+}
+
+void testBlockInCriticalSectionWithNestedMutexes() {
+  std::mutex m, n, k;
+  m.lock();
+  n.lock();
+  k.lock();
+  sleep(3); // expected-warning {{Block in a critical section}}
+  k.unlock();
+  sleep(5); // expected-warning {{Block in a critical section}}
+  n.unlock();
+  sleep(3); // expected-warning {{Block in a critical section}}
+  m.unlock();
+  sleep(3); // no-warning
+}
Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -8,6 +8,7 @@
   ArrayBoundChecker.cpp
   ArrayBoundCheckerV2.cpp
   BasicObjCFoundationChecks.cpp
+  BlockInCriticalSectionChecker.cpp
   BoolAssignmentChecker.cpp
   BuiltinFunctionChecker.cpp
   CStringChecker.cpp
Index: lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -0,0 +1,111 @@
+//===-- BlockInCriticalSectionChecker.cpp ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// Defines a checker for blocks in critical sections. This checker should find 
+// the calls to blocking functions (for example: sleep, getc, fgets, read, 
+// recv etc.) inside a critical section. When sleep(x) is called while a mutex
+// is held, other threades cannot lock the same mutex. This might take some 
+// time, leading to bad performance or even deadlock.
+//
+//===--===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+
+class BlockInCriticalSectionChecker : public Checker {
+
+  CallDescription LockFn, UnlockFn, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn;
+
+  std::unique_ptr BlockInCritSectionBugType;
+
+  void reportBlockInCritSection(SymbolRef FileDescSym,
+const CallEvent ,
+CheckerContext ) const;
+
+public:
+  BlockInCriticalSectionChecker();
+
+  /// Process lock.
+  /// Process blocking functions (sleep, getc, fgets, read, recv)
+  void checkPostCall(const CallEvent , CheckerContext ) const;
+
+  /// Process unlock.
+  void checkPreCall(const CallEvent , CheckerContext ) const;
+
+};
+
+} // end anonymous namespace
+
+REGISTER_TRAIT_WITH_PROGRAMSTATE(Counter, unsigned)
+
+BlockInCriticalSectionChecker::BlockInCriticalSectionChecker()
+: LockFn("lock"), UnlockFn("unlock"), SleepFn("sleep"), GetcFn("getc"),
+  FgetsFn("fgets"), ReadFn("read"), RecvFn("recv") {
+  // Initialize the bug type.
+  BlockInCritSectionBugType.reset(
+  new BugType(this, "Block in critical section", "Unix Stream API Error"));
+}
+
+void BlockInCriticalSectionChecker::checkPostCall(const CallEvent ,
+