...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> #include <threads.h> enum { NTHREADS = 5 }; mtx_t mutex; cnd_t cond; int run_step(void *t) { static int current_step = 0; int my_step = (int)t; int result; if ((result = mtx_lock(&mutex)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d has the lock\n", my_step); while (current_step != my_step) { printf("Thread %d is sleeping...\n", my_step); if ((result = cnd_wait(&cond, &mutex)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d woke up\n", my_step); } /* Do processing... */ printf("Thread %d is processing...\n", my_step); current_step++; /* Signal a waiting task. */ if ((result = cnd_signal(&cond)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d is exiting...\n", my_step); if ((result = mtx_unlock(&mutex)) != thrd_success) { /* Handle error condition. */ } return 0; } int main(int argc, char** argv) { int i; int result; thrd_t threads[NTHREADS]; int step[NTHREADS]; if ((result = mtx_init(&mutex, mtx_plain)) != thrd_success) { /* Handle error condition. */ } if ((result = cnd_init(&cond)) != thrd_success) { /* Handle error condition. */ } /* Create threads. */ for (i = 0; i < NTHREADS; i++i) { step[i] = i; if ((result = thrd_create(&threads[i], run_step, (void *)step[i])) != thrd_success) { /* Handle error condition */ } } /* Wait for all threads to complete. */ for (i = NTHREADS - 1; i >= 0; i--i) { if ((result = thrd_join(threads[i], NULL)) != != thrd_success) { /* Handle error condition */ } } mtx_destroy(&mutex); cnd_destroy(&cond); return 0; } |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <threads<stdio.h> #include <stdio<threads.h> int run_step(void *t) { static int current_step = 0; int my_step = (int)t; int result; if ((result = mtx_lock(&mutex)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d has the lock\n", my_step); while (current_step != my_step) { printf("Thread %d is sleeping...\n", my_step); if ((result = cnd_wait(&cond, &mutex)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d woke up\n", my_step); } /* Do processing... */ printf("Thread %d is processing...\n", my_step); current_step++; /* Signal ALL waiting tasks. */ if ((result = cnd_broadcast(&cond)) != thrd_success) { /* Handle error condition */ } printf("Thread %d is exiting...\n", my_step); if ((result = mtx_unlock(&mutex)) != 0) { /* Handle error condition */ } return 0; } |
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <Windows.h>
#include <stdio.h>
CRITICAL_SECTION lock;
CONDITION_VARIABLE cond;
DWORD WINAPI run_step(LPVOID t) {
static int current_step = 0;
int my_step = (int)t;
int result;
EnterCriticalSection(&lock);
printf("Thread %d has the lock\n", my_step);
while (current_step != my_step) {
printf("Thread %d is sleeping...\n", my_step);
if (!SleepConditionVariableCS(&cond, &lock, INFINITE)) {
/* Handle error condition. */
}
printf("Thread %d woke up\n", my_step);
}
/* Do processing... */
printf("Thread %d is processing...\n", my_step);
current_step++;
LeaveCriticalSection(&lock);
/* Signal ALL waiting tasks. */
WakeAllConditionVariable(&cond);
printf("Thread %d is exiting...\n", my_step);
return 0;
}
enum { NTHREADS = 5 };
int main(int argc, char** argv) {
int i;
HANDLE threads[NTHREADS];
InitializeCriticalSection(&lock);
InitializeConditionVariable(&cond);
/* Create threads Create threads. */
for (int i = 0; i < NTHREADS; i ++i) {
threads[i] = CreateThread(NULL, 0, run_step, (LPVOID)i, 0, 0);
}
/* Wait for all threads to complete */
WaitForMultipleObjects(NTHREADS, threads, TRUE, INFINITE);
DeleteCriticalSection
NULL);
}
/* Wait for all threads to complete. */
WaitForMultipleObjects(NTHREADS, threads, TRUE, INFINITE);
DeleteCriticalSection(&lock);
return 0;
} |
Compliant Solution (Using cnd_signal() but with a Unique Condition Variable per Thread)
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> #include <threads.h> enum { NTHREADS = 5 }; mtx_t mutex; cnd_t cond[NTHREADS]; int run_step(void *t) { static int current_step = 0; int my_step = (int)t; int result; if ((result = mtx_lock(&mutex)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d has the lock\n", my_step); while (current_step != my_step) { printf("Thread %d is sleeping...\n", my_step); if ((result = cnd_wait(&cond[my_step], &mutex))], &mutex)) != thrd_success) { /* Handle error condition. */ } printf("Thread %d woke up\n", my_step); } /* Do processing... */ printf("Thread %d is processing...\n", my_step); current_step++; /* Signal next step thread. */ if ((my_step + 1) < NTHREADS) { if ((result = cnd_signal(&cond[my_step + 1])) != thrd_success) { /* Handle error condition */ } } printf("Thread %d is exiting...\n", my_step); if ((result = mtx_unlock(&mutex)) != thrd_success) { /* Handle error condition. */ } return 0; } int main(int argc, char** argv) { int i; int result; thrd_t threads[NTHREADS]; int step[NTHREADS]; if ((result = mtx_init(&mutex, mtx_plain)) != thrd_success) { /* Handle error condition. */ } for (i = 0; i< NTHREADS; i++i) { if ((result = cnd_init(&cond[i])) != thrd_success) { /* Handle error condition. */ } } /* Create threads. */ for (i = 0; i < NTHREADS; i++i) { step[i] = i; if ((result = thrd_create(&threads[i], run_step,[i], run_step, (void *)step[i])) != thrd_success) { /* Handle error condition. */ } } /* Wait for all threads to complete. */ for (i = NTHREADS - 1; i >= 0; i--i) { if ((result = thrd_join(threads[i], NULL)) != thrd_success) { /* Handle error condition. */ } } mtx_destroy(&mutex); for (i = 0; i < NTHREADS; i++i) { cnd_destroy(&cond[i]); } return 0; } |
...
Signaling a single thread instead of all waiting threads can pose a threat to the liveness property of the system.
GuidelineRule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
CON38-C | low | unlikely | medium | P2 | L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
| CERT Oracle Secure Coding Standard for Java | THI04-J. Notify all waiting threads rather than a single thread |
...
...