Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

If a lock is being held and an operation that can block is performed, any other thread that needs to acquire that lock may also block. This can condition can degrade the system performance of a system or cause a deadlock to occur.  Blocking calls include, but are not limited to, network, file, and console I/O.

Using a blocking operation while holding a lock may be unavoidable for a portable solution. For instance, file access could be protected via a lock to prevent multiple threads from mutating the contents of the file. Or, a thread may be required to block while holding one or more locks and waiting to acquire another lock. In these cases, attempt to hold the lock for the least time required. Additionally, if acquiring multiple locks, the order of locking must avoid deadlock, as specified in CON35-C. Avoid deadlock by locking in a predefined order.

Noncompliant Code Example

This noncompliant code example demonstrates an occurrence of a blocking call that waits to receive data on a socket example calls fopen() while a mutex is locked. The recv(…) call will block until data arrives on the socket. While it’s calls to fopen() and fclose() are blocking and may block for an extended period of time if the file resides on a network drive. While the call is blocked, other threads that are waiting for the lock will are also be blocked.

Although this example is specific to network I/O, the recv(…) call could be replaced with any blocking call and the same behavior would occur.

Code Block
bgColor#ffcccc
langc

pthread_mutexattr_t attr;
pthread_mutex_#include <stdio.h>
#include <threads.h>
 
mtx_t mutex;

voidint thread_foo(void \*ptr) {
  uint32_t num;
  int result;
  intFILE sock;

  /* sock is a connected TCP socket */*fp;

  if ((result = pthread_mutexmtx_lock(&mutex)) \!= 0thrd_success) {
       /* Handle Errorerror */
   }
 
  iffp ((result = recvfopen(sock, (void \*)&num, sizeof(uint32_t), 0)) < 0"SomeNetworkFile", "r");
  if (fp != NULL) {
       /* Work with Handlethe errorfile */
   }

  /* ... */
fclose(fp);
  }
 
  if ((result = pthread_mutexmtx_unlock(&mutex)) \!= 0thrd_success) {
       /* Handle Errorerror */
   }

  return 0;
}

int main(void) {
  pthreadthrd_t thread;
  int result;

  if ((result = pthreadmtx_mutexattr_settype(
      init(&mutex, PTHREADmtx_MUTEX_ERRORCHECKplain)) \!= 0thrd_success) {
    /* Handle Error */
  }

  if ((result = pthread_mutex_init(&mutex, &attr)) \!= 0) {
    /* Handle Errorerror */
   }

  if (pthreadthrd_create(&thread,NULL,(void \*)& thread_foo, NULL) \!= 0thrd_success) {
       /* Handle Errorerror */
   }

  /* ... */

  pthreadif (thrd_join(thread, NULL);

  if ((result  != pthread_mutex_destroy(&mutex)) \!= 0) {
   thrd_success) {
    /* Handle error */
   }

  mtx_destroy(&mutex);

  return 0;
}

Compliant Solution (Block while

...

Not Locked)

This compliant solution performs the recv(…) call file operations when the lock has not been acquired. This causes the blocking behavior to only affect The blocking behavior consequently affects only the thread that called the blocking function.

Code Block
bgColor#ccccff
langc

void#include <stdio.h>
#include <threads.h>
 
mtx_t mutex;
 
int thread_foo(void \*ptr) {
  uint32_t num;
int result;
int sock;

 FILE /* sock is a connected TCP socket */

  if ((result = recv(sock, (void \*)&num, sizeof(uint32_t), 0)) < 0) {
    /* Handle error */
  }
*fp = fopen("SomeNetworkFile", "r");
 
  if ((result = pthread_mutex_lock(&mutex)) \fp != 0NULL) {
    /* Handle Error */
  }

  /* ... */

  if ((result = pthread_mutex_unlock(&mutex)) \!= 0) {
    /* Handle Error */
  }
}

Compliant Solution (Use a non-blocking call)

This compliant solution performs the recv(…) call with the parameter o_nonblock, which causes the call to fail if there are no messages available on the socket.

Code Block
bgColor#ccccff

void thread_foo(void \*ptr) {
  uint32_t num;
  int result;

  /* sock is a connected TCP socket */

  if ((result = recv(sock, (void \*)&num, sizeof(uint32_t), O_NONBLOCK)) < 0) {
    /* Handle error */
  Work with the file */
    fclose(fp);
  }

  if ((result = pthreadmtx_mutex_lock(&mutex)) \!= 0thrd_success) {
       /* Handle Errorerror */
   }

  /* ... */

  if ((result = pthread_mutex_unlock(&mutex)) \!= 0) {
       /* Handle Errorerror */
   }
}

Exceptions

...


  return 0;
}

Risk Assessment

Blocking or lengthy operations performed within synchronized regions could result in a deadlocked or an unresponsive system.

Rule

Recommendation

Severity

Likelihood

Remediation Cost

Detectable

Level

Repairable

Priority

CON36

Level

CON05-C

Low

Probable

low

No

probable

No

high

L3

P2

Related Guidelines

P2

L3

Automated Detection

ToolVersionCheckerDescription
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

CONCURRENCY.STARVE.BLOCKING

Blocking in critical section
Klocwork
Include Page
Klocwork_V
Klocwork_V
CONC.SLEEP
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V
CERT_C-CON05-a
Do not use blocking functions while holding a lock
Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. CON05-CChecks for blocking operation while holding lock (Rec. partially covered)
Security Reviewer - Static Reviewer

6.02

C12Fully Implemented

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Key here (explains table format and definitions)

...

Taxonomy

Taxonomy item

Relationship

...

...

Prior to 2018-01-12: CERT: Unspecified Relationship
MITRE CWECWE-557Prior to 2018-01-12:
MITRE CWECWE-662Prior to 2018-01-12:


...

Image Added Image Added Image Added

Bibliography

Wiki Markup
\[[Barney 2010|AA. Bibliography#Barney 10]\] [POSIX Threads Programming|https://computing.llnl.gov/tutorials/pthreads/]

Wiki Markup\[[Open Group|AA. Bibliography#OpenGroup04]\] [pthread_cancel()|http://www.opengroup.org/onlinepubs/009695399/functions/pthread_cancel.html]{{,}} [recv()|http://www.opengroup.org/onlinepubs/009695399/functions/recv.html]\\