I am really at a loss here.
i read the MSDN articles thoroughly but still cant figure out what is going on.
my problem is this: when running a few processes with the following code all is working:
HANDLE m = CreateMutex(NULL, FALSE, L"MyMutex");
char c[20] = "2print";
for(int iter = 0; iter<100; ++iter) {
WaitForSingleObject(m,INFINITE);
for(int i=0;i<(int)strlen(c);++i) {
for(int j=0;j<10000;++j)
printf("%c",c[i]);
}
BOOL ok = ReleaseMutex(m);
}
CloseHandle(m);
that is, the different processes each printing at its own turn and releasing the mutex until all printing is done.
BUT changing the CreateMutex to: (bInitialOwner from FALSE to TRUE)
HANDLE m = CreateMutex(NULL, TRUE, L"MyMutex");
the first creator will not release the mutex! other processes are just sitting there.
what amazed me was, that by adding an additional releaseMutex, that is changing:
BOOL ok = ReleaseMutex(m);
into:
BOOL ok = ReleaseMutex(m);
ok = ReleaseMutex(m);
make it work!
i am really confused, why wouldnt the first creator release the mutex correctly?
i tried printing all the errors using GetLastError, and what i get seem reasonable, like ERROR_ALREADY_EXISTS for the creators following the first one, which is just what i expect (MSDN says that in this situation the bInitialOwner is simply ignored).
When you use bInitialOwner=TRUE, the mutex creator automatically acquires the mutex. Then when you call WaitForSingleObject, it acquired the mutex again. Since win32 mutexes are recursive mutexes, you must release once for each time you acquired the mutex - so two ReleaseMutex calls are needed for the initial creator (however every other thread must only release once!)
You can avoid this by either not using bInitialOwner, or by skipping the WaitForSingleObject on the first loop only if any only if GetLastError() != ERROR_ALREADY_EXISTS. You will need to call SetLastError(0) prior to CreateMutex to clear the error code if you choose the latter.
If you only need bInitialOwner for some kind of initial setup, it will simplify your code if you drop the mutex prior to entering the common loop. Otherwise, I would strongly recommend simply not using bInitialOwner, unless you have a compelling reason to do so.
Related
I am using pthread condition variable as a synchronization primitive in a ping-pong test. The ping-pong test consists of two threads execute alternatively. Each thread writes to the other thread's memory and wake it up using signal, then wait and sleep on its own memory which will be written by the other thread later. Here is my first version. It works fine when I loop this ping-pong test for 10,000 times, but when I change to 100,000 times, it will hang occasionally. N=1,000,000 will make it hang definitely. I tried to debug and print out the loop number for each loop, but the program never hangs again after I add the print statement, which is annoying. Here is the ping-pong test code:
for(i=0; i<N+1; i++)
{
if(i==N)
{
pthread_cond_signal(&cond[dest]);
break;
}
pthread_mutex_lock(&mutex[dest]);
messages[dest]=my_rank;
pthread_cond_signal(&cond[dest]);
pthread_mutex_unlock(&mutex[dest]);
pthread_mutex_lock(&mutex[my_rank]);
while(pthread_cond_wait(&cond[my_rank], &mutex[my_rank]) && messages[my_rank]!=dest);
messages[my_rank]=my_rank;
pthread_mutex_unlock(&mutex[my_rank]);
printf("rank=%ld i=%ld messages[%ld]=%ld\n", my_rank, i, my_rank, messages[my_rank]);
}
Then I tried a second version which works and never hangs, even I set N to 1,000,000. I changed from two mutexes to one mutex which is shared by the two condition variables. I am not sure if it is the right way to go but this one never hangs again. Here is the code:
for(i=0; i<N+1; i++)
{
if(i==N)
{
pthread_cond_signal(&cond[dest]);
break;
}
pthread_mutex_lock(&mutex[0]);
messages[dest]=my_rank;
pthread_cond_signal(&cond[dest]);
while(pthread_cond_wait(&cond[my_rank], &mutex[0]) && messages[my_rank]!=dest);
messages[my_rank]=my_rank;
pthread_mutex_unlock(&mutex[0]);
}
I am very confused. Could somebody help me explain why the first version hangs but the second version does not? Is it correct for two condition variable sharing a single mutex?
Thanks.
Thanks for everyone, especially caf. Here is my final code that works without hanging.
for(i=0; i<N+1; i++)
{
pthread_mutex_lock(&mutex[dest]);
messages[dest]=my_rank;
pthread_cond_signal(&cond[dest]);
pthread_mutex_unlock(&mutex[dest]);
if(i!=N)
{
pthread_mutex_lock(&mutex[my_rank]);
while(messages[my_rank]!=dest)
pthread_cond_wait(&cond[my_rank], &mutex[my_rank]);
messages[my_rank]=my_rank;
pthread_mutex_unlock(&mutex[my_rank]);
}
}
The problem is in this line:
while (pthread_cond_wait(&cond[my_rank], &mutex[my_rank]) && messages[my_rank]!=dest);
If the 'dest' thread gets scheduled after you unlock mutex[dest] and before you lock mutex[my_rank], it will set messages[my_rank] and signal the condition variable, before this thread calls pthread_cond_wait(), so this thread will wait forever.
The fix for this is very easy: test messages[my_rank] before waiting on the condition variable. You also don't want && here, because you always want to keep looping as long as messages[my_rank] != dest is true - you don't want to break out at the first non-zero return from pthread_cond_wait(). So if you want to ignore errors from pthread_cond_wait() (as your original does, and this is perfectly fine if you aren't using error-checking or robust mutexes, since those are the only times pthread_cond_wait() is allowed to fail), use:
while (messages[my_rank] != dest)
pthread_cond_wait(&cond[my_rank], &mutex[my_rank]);
The reason that your alternate version doesn't have this bug is because the lock is continuously held between signalling the dest thread and waiting on the condition variable, so the dest thread doesn't get a chance to run until we're definitely waiting.
As for your supplementary question:
Is it correct for two condition variable sharing a single mutex?
Yes, this is allowed, but the converse is not (you cannot have two threads waiting on the same condition variable at the same time, using different mutexes).
first of all, sorry, i wanted to put that into comment but i still can not.
Well, in your code, i don't understand much what is "my_rank" and "dest", as i think my_rank should maybe vary within those loops, but i have found the following that may help you : http://www.cs.cf.ac.uk/Dave/C/node31.html#SECTION003125000000000000000
there it's said :
You should always call pthread_cond_signal() under the protection of the same mutex used with the condition variable being signaled. Otherwise, the condition variable could be signaled between the test of the associated condition and blocking in pthread_cond_wait(), which can cause an infinite wait.
As you're using multiple mutexes in the first version, that may be the reason.
an admin could move that to comments, please?
I'm creating a function that searches through a directory, prints out files, and when it runs into a folder, a new thread is created to run through that folder and do the same thing.
It makes sense to me to use recursion then as follows:
pthread_t tid[500];
int i = 0;
void *search(void *dir)
{
struct dirent *dp;
DIR *df;
df = opendir(dir)
char curFile[100];
while ((dp = readdir(df)) != NULL)
{
sprintf(curFile, "%s/%s",dir,dp->d_name);
if(isADirectory(curFile))
{
pthread_create(&tid[i], NULL, &search, &curFile);
i++;
}
else
{
printf("%s\n", curFile);
}
}
pthread_join(&tid[i])
return 0;
}
When I do this, however, the function ends up trying to access directories that don't actually exist. Initially I had pthread_join() directly after pthread_create(), which worked, but I don't know if you can count that as multithreading since each thread waits for its worker thread to exit before doing anything.
Is the recursive aspect of this problem even possible, or is it necessary for a new thread to call a different function other than itself?
I haven't dealt with multithreading in a while but if memory serves threads share resources. Which means (in your example) every new thread you make accesses the same variable "i". Now if those threads only read variable "i" there would be no problem whatsoever (every thread keeps reading ... i = 2 wohoo :D).
But issues arise when threads share resources that are being read and written on.
i = 2
i++
// there are many threads running this code
// and "i" is shared among them, are you sure i = 3?
Read, write on shared resources problem is solved with thread synchronization. I recommend reading/googling upon it since it's a pretty unique topic to be solved in one question.
P.S. I pointed out variable "i" in your code but there may be more such resources since your code doesn't display any attempt at thread synchronization.
Consider your while loop. Inside it you have:
sprintf(curFile, "%s/%s",dir,dp->d_name);
and
pthread_create(&tid[i], NULL, &search, &curFile);
So, you mutate the contents of curFile inside the loop, and you also create a thread which you are trying to pass the current contents of curFile. This is a spectacular race hazard - there is no guarantee that the new thread will see the intended contents of curFile, since it may have changed in the meantime. You need to duplicate the string and pass the new thread a copy which won't be mutated by the calling thread. The thread is therefore also going to have be responsible for deallocating the copy, which means either that the search method do exactly that or that you have a second method.
You have another race condition in using i and tid in all threads. As I have suggested in the comment on your question, I think these variables should be method local.
In general I suggest that you read on thread safety and learn about data race hazards before you attempt to use threads. It is usually best to avoid the use of threads unless you really need the extra performance.
I am new to C and wanted to know about race conditions. I found this on the internet and it asked to find the race condition, and a solution to it.
My analysis is that the race condition is in the create-thread() method has the race condition, specifically in the if-else statement. So when the method is being accessed another thread could be created or removed during the check-and-act and the thread_amt would be off.
In order to not have the race condition, then lock the if-else using mutex, semaphores, etc?
Can anyone correct me if I am wrong, and could possibly show me how to implement mutex?
#define MAXT 255
int threads_amt = 0;
int create-thread() // create a new thread
{
int tid;
if (threads_amt == MAXT) return -1;
else
{
threads_amt++;
return tid;
}
}
void release-thread()
{
/* release thread resources */
--threads_amt;
}
Yeah, the race condition in this case happens because you have no guarantee that the checking and the manipulation of threads_amt are going to happen with no interruption/execution of another thread.
Three solutions off the top of my head:
1) Force mutual exclusion to that part of code using a binary semaphore (or mutex) to protect the if-else part.
2) Use a semaphore with initial value MAXT, and then, upon calling create_thread (mind, you can't use hyphens in function names!), use "wait()" (depending on the type of semaphore, it could have different names (such as sem_wait())). After that, create the thread. When calling release_thread(), simply use "signal()" (sem_post(), when using semaphore.h).
3) This is more of an "hardware" solution: you could assume that you are given an atomic function that performs the entire if-else part, and therefore avoids any race condition problem.
Of these solutions, the "easiest" one (based on the code you already have) is the first one.
Let's use semaphore.h's semaphores:
#define MAXT 255
// Global semaphore
sem_t s;
int threads_amt = 0;
int main () {
...
sem_init (&s, 0, 1); // init semaphore (initial value = 1)
...
}
int create_thread() // create a new thread
{
int tid;
sem_wait(&s);
if (threads_amt == MAXT) {
sem_post(&s); // the semaphore is now available
return -1;
}
else
{
threads_amt++;
sem_post(&s); // the semaphore is now available
return tid;
}
}
void release_thread()
{
/* release thread resources */
sem_wait(&s);
--threads_amt;
sem_post(&s);
}
This should work just fine.
I hope it's clear. If it's not, I suggest that you study how semaphores work (use the web, or buy some Operating System book). Also, you mentioned that you are new to C: IMHO you should start with something easier than this: semaphores aren't exactly the next thing you want to learn after the 'hello world' ;-)
The race condition is not in the if() statements.
It is with access to the variable threads_amt that is potentially changed and accessed at the same time in multiple threads.
Essentially, any thread that modifies the variable must have exclusive access to avoid a race condition. That means all code which modifies the variable or reads its value must be synchronised (e.g. grab a mutex first, release after). Readers don't necessarily need exclusive access (e.g. two threads reading at the same time won't necessarily affect each other) but writers do (so avoid reading a value while trying to change it in another thread) - such considerations can be opportunities to use synchronisation methods other than a mutex - for example, semaphores.
To use a mutex, it is necessary to create it first (e.g. during project startup). Then grab it when needed, and remember to release it when done. Every function should minimise the time that it holds the mutex, since other threads trying to grab the mutex will be forced to wait.
The trick is to make the grabbing and releasing of the mutex unconditional, wherever it occurs (i.e. avoid a function that grabs the mutex, being able to return without releasing it). That depends on how you structure each function.
The actual code for implementing depends on which threading library you're using (so you need to read the documentation) but the concepts are the same. All threading libraries have functions for creating, grabbing (or entering), and releasing mutexes, semaphores, etc etc.
I've the following source code (adapted from my original code):
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include "pthread.h"
#define MAX_ENTRY_COUNT 4
int entries = 0;
bool start = false;
bool send_active = false;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condNotEmpty = PTHREAD_COND_INITIALIZER;
pthread_cond_t condNotFull = PTHREAD_COND_INITIALIZER;
void send()
{
for (;;) {
if (!start)
continue;
start = false;
for(int i = 0; i < 11; ++i) {
send_active = true;
pthread_mutex_lock(&mutex);
while(entries == MAX_ENTRY_COUNT)
pthread_cond_wait(&condNotFull, &mutex);
entries++;
pthread_cond_broadcast(&condNotEmpty);
pthread_mutex_unlock(&mutex);
send_active = false;
}
}
}
void receive(){
for(int i = 0; i < 11; ++i){
pthread_mutex_lock(&mutex);
while(entries == 0)
pthread_cond_wait(&condNotEmpty, &mutex);
entries--;
pthread_cond_broadcast(&condNotFull);
pthread_mutex_unlock(&mutex);
}
if (send_active)
printf("x");
}
int _tmain(int argc, _TCHAR* argv[])
{
pthread_t s;
pthread_create(&s, NULL, (void *(*)(void*))send, NULL);
for (;;) {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&condNotEmpty, NULL);
pthread_cond_init(&condNotFull, NULL);
start = true;
receive();
pthread_mutex_destroy(&mutex);
mutex = NULL;
pthread_cond_destroy(&condNotEmpty);
pthread_cond_destroy(&condNotFull);
condNotEmpty = NULL;
condNotFull = NULL;
printf(".");
}
return 0;
}
The problem is like follows: from time to time the last unlock in the send function is not finished before the receive method continues. In my original code the mutexes are located in an objects which are deleted after doing the job. If the send method has not finished with the last unlock then the mutexes are invalid and my program causes failures in unlock.
The behavior can be easily reproduced by running the program: each time the "x" is diplayed the receive method has nearly finished and the send method "hangs" in the unlock call.
I've compiled with VS2008 and VS2010 - both results are same.
pthread_mutex_unlock is not atomic, this would solve the problem. How can I solve this issue? Any comments are welcome...
Best regards
Michael
Your printf("x") is a textbook race condition example.
After pthread_mutex_unlock() OS is free to not schedule this thread for any amount of time: ticks, seconds or days. You can't assume that send_active will be "falsified" in time.
pthread_mutex_unlock() must by definition release the mutex before it returns. The instant the mutex is released, another thread that's contending for the mutex could be scheduled. Note that even if pthread_mutex_unlock() could arrange to not release the mutex until just after it returned (what I think you mean by it being atomic), there would still be an equivalent race condition to whatever you're seeing now (it's not clear to me what race you're seeing since a comment indicates that ou're not realy interested in the race condition of accessing send_active to control the printf() call).
In that case the other thread could be scheduled 'between-the-lines' of the pthread_mutex_unlock() and the following statement/expression in the function that called it - you'd have the same race condition.
Here's some speculation on what might be happening. A couple caveats on this analysis:
this is based on the assumption that you're using the Win32 pthreads package from http://sourceware.org/pthreads-win32/
this is based only on a pretty brief examination of the pthreads source on that site and the information in the question and comments here - I have not had an opportunity to actually try to run/debug any of the code.
When pthread_mutex_unlock() is called, it decrements a lock count, and if that lock count drops to zero, the Win32 SetEvent() API is called on an associated event object to let any threads waiting on the mutex to be unblocked. Pretty standard stuff.
Here's where the speculation comes in. Lets say that SetEvent() has been called to unblock thread(s) waiting on the mutex, and it signals the event associated with the handle it was given (as it should). However, before the SetEvent() function does anything else, another thread starts running and closes the event object handle that that particular SetEvent() was called with (by calling pthread_mutex_destroy()).
Now the SetEvent() call in progress has a handle value that's no longer valid. I can't think of a particular reason that SetEvent() would do anything with that handle after it's signaled the event, but maybe it does (I could also imagine someone making a reasonable argument that SetEvent() should be able to expect that the event object handle remain valid for the duration of the API call).
If this is what's happening to you (and that's a big if), I'm not sure if there's an easy fix. I think that the pthreads library would have to have changes made so that it duplicated the event handle before calling SetEvent() then close that duplicate when the SetEvent() call returned. That way the handle would remain valid even if the 'main' handle were closed by another thread. I'm guessing it would have to do this in a number of places. This could be implemented by replacing the affected Win32 API calls with calls to wrapper functions that perform the "duplicate handle/call API/close duplicate" sequence.
It might not be unreasonable for you to try to make this change for the SetEvent() call in pthread_mutex_unlock() and see if it solves (or at least improves) your particular problem. If so, you may want to contact the maintainer of the library to see if a more comprehensive fix might be arranged somehow (be prepared - you may be asked to do a significant part of the work).
Out of curiosity, in your debugging of the state of the thread that hangs in pthread_mutex_unlock()/SetEvent(), do you have any information on exactly whats happening? What SetEvent() is waiting for? (the cdb debugger that's in the Debugging Tools for Windows package might be able to give you more information about this than the Visual Studio debugger).
Also, note the following comment in the source for pthread_mutex_destroy() which seems related (but different) than your particular problem:
/*
* FIXME!!!
* The mutex isn't held by another thread but we could still
* be too late invalidating the mutex below since another thread
* may already have entered mutex_lock and the check for a valid
* *mutex != NULL.
*
* Note that this would be an unusual situation because it is not
* common that mutexes are destroyed while they are still in
* use by other threads.
*/
Michael, thank you for your investigation and comments!
The code I'm using is from http://sourceware.org/pthreads-win32/.
The situation described by you in the third and fourth paragraph is exactly what's happening.
I've checked some solutions and a simple one seems to work for me: I waiting till the send function (and SetEvent) has finished. All my tests with this solution were successful till now. I'm going to do a larger test over the weekend.
I am supposed to implement a userlevel threads library in C. To do so, I need to implement yield(), createThread() and destroyThread() functions. I believe I've got the basics right:
To keep track of threads, I'll use a queue of ThreadControlBlock elements (which resemble PCBs in an OS) that look like this:
struct ThreadControlBlock {
int ThreadId,
u_context *context };
We can use the setcontext() family of functions to "save" and "load" the context.
Upon initialization of the program, initialize ThreadQueue with no elements.
Now the part I am not getting: when a thread calls yield(), I get the current context and save it in a ThreadControlBlock and put in the queue. Then get the first element in the queue and load the context in it, and execution proceeds.
The question is, if I do this, say I am a thread calling yield() and the next thread is myself. If I am saving the context and loading it again, upon re-entering wouldn't I be at the exact same spot where I was (before calling yield()?) And this would keep going on forever?
When a thread calls yield(), you have to save the state of a thread that's about to return from a yield() call. Don't save the context from immediately before the yield().
The same issue actually applies if you're switching to another task, too - since that other task saved its context at the same point (where it was about to switch to a second task). Using setcontext() and getcontext(), you need to use a static variable to keep track of whether you're switching in or switching out:
static volatile int switched;
switched = 0;
getcontext(current->context);
if (!switched)
{
switched = 1;
setcontext(next->context);
}
Alternatively, you can just use swapcontext(current->context, next->context);
It's perfectly reasonable in your yield() implementation to check to see if the next thread is the current thread and treat that case as a no-op.
If there are no other threads to run besides the current thread then there is nothing else to do besides just return from yield. I wouldn't bother with calling swapcontext in this case, though -- just detect and return.
I think that what you are actually dealing with is what to do when no threads (including the current one) when yield is called. An easy way to deal with this is to have an idle thread, which is only run when the run queue (ready threads) is empty. This thread will probably just:
{
while (1) {
yield();
pause();
}
}
This allows your program to go to sleep (via pause) until a signal happens. Hopefully the signal will be some event that makes one of the other threads ready to run, so the next call to yield will run the other thread instead of running the idle thread again.