My application gives certain works to the worker agency to execute in a thread pool thread as given below
void Execute ProcessWork
{
int nRes = 0;
CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork();
// Incorrect use of stack variable
pProcessMessageWork->m_pStatus = &nRes;
// Worker Agency
m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork);
}
The definition of CFireProcessMessageWork is given below. The DoWork method of the class given below will be executed in a worker thread. Since the variable nRes is used in an improper way, my application crashes occasionally. I spent almost a week to identify the cause of the issue. I tried page heap with full options and Stack Frames (/RTCs) to detect the issue. But the application crashed at a location which has no relationship with the issue.
Is there any tools microsoft provides to detect these kind of issues?
class CFireProcessMessageWork
{
public:
int *m_pStatus;
public:
CFireProcessMessageWork()
{
m_pStatus = NULL;
}
int DoWork()
{
// Using Address of nRes
*mpStatus = 0;
// Do Some Work and Pass mpStatus to fill the error code
HRESULT hRes = pGEMMessageEvents->ProcessMessage(varData, m_nMsgCount, m_newTkt,m_idxFunc,&m_nRetVal);
return *mpStatus
}
}
The problem is that each one of those lines makes sense to the compiler. There is nothing wrong with them, and just the combination is not really good. Even then, it would require a good amount of extra work and analysis to determine that it is a wrong use.
Consider for example, that you could be joining the worker thread in the same function, and then everything would be correct, if the function did not process in a different thread but just manipulated the code in the SubmitWork call, then it would be correct... and the compiler does not necessarily know about threads, so the fact is that it is almost impossible for the compiler to detect this.
On the other hand, this is something that should be quite obvious to a reviewer, so it can be better tackled by reviewing code. Other possible options would be using some form of shared ownership to handle the resources --which might imply more cost:
void Execute ProcessWork {
std::shared_ptr<int> nRes = std::make_shared<int>( 0 );
CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork();
pProcessMessageWork->m_pStatus = nRes; // copies the shared_ptr
m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork);
}
In this case, the shared ownership of the object at the cost of an extra allocation, guarantees that the thread will not cause undefined behavior while updating the state. But while this will make the program correct from a language point of view, it might still be undesired: the status will not be readable outside of the worker thread, as the only other reference is outside of the worker control.
You are writing a syntactically valid code here by passing &nRes, however since it is a local varaible in stack and it is being accessed in some other thread, the address is not going to be valid, resulting in crash. I think a careful peer code review should help resolve such issues.
Related
I'd like to have an object in C++ that does an asynchronous task in the background, but can still be requested to be freed by code using it without breaking things.
Let's say I have an object like this:
class MyObj {
std::thread* asyncTask;
bool result;
public:
MyObj() {
asyncTask = new std::thread([this](){
result = doSomething();
});
};
bool isResult() {
return result;
};
}
How would you go about making sure that the object can still be freed without terminating the process(due to thread still joinable/running at time of destruction)? I've thought about something involving delaying the destructor with a thread running counter, but that doesn't seem like the right solution. Part of the complexity is that the thread needs to normally access elements of the class, so it can't just detach either.
The only way to do this in general is to create a new process to handle the task (expensive, lots of marshalling and busywork), or have the thread cooperate.
A thread that cooperates regularly checks if it should abort. When it detects it should abort, it does so. It has to do this even when it is blocking on some resource.
For simple tasks, this is simple. For general tasks, next to impossible.
C++ compilers basically assume the threads get to act single threaded unless you go and explicitly synchronize operations. This permits certain important optimizations. The cost is that the state of a C++ thread need not make any sense at any point; so killing it or suspending it externally cannot be made safe (without cooperation).
In short, write your doSomething with cooperation and abort in mind.
In Microsoft Visual C++ I can call CreateThread() to create a thread by starting a function with one void * parameter. I pass a pointer to a struct as that parameter, and I see a lot of other people do that as well.
My question is if I am passing a pointer to my struct how do I know if the structure members have been actually written to memory before CreateThread() was called? Is there any guarantee they won't be just cached? For example:
struct bigapple { string color; int count; } apple;
apple.count = 1;
apple.color = "red";
hThread = CreateThread( NULL, 0, myfunction, &apple, 0, NULL );
DWORD WINAPI myfunction( void *param )
{
struct bigapple *myapple = (struct bigapple *)param;
// how do I know that apple's struct was actually written to memory before CreateThread?
cout << "Apple count: " << myapple->count << endl;
}
This afternoon while I was reading I saw a lot of Windows code on this website and others that passes in data that is not volatile to a thread, and there doesn't seem to be any memory barrier or anything else. I know C++ or at least older revisions are not "thread aware" so I'm wondering if maybe there's some other reason. My guess would be the compiler sees that I've passed a pointer &apple in a call to CreateThread() so it knows to write out members of apple before the call.
Thanks
No. The relevant Win32 thread functions all take care of the necessary memory barriers. All writes prior to CreateThread are visible to the new thread. Obviously the reads in that newly created thread cannot be reordered before the call to CreateThread.
volatile would not add any extra useful constraints on the compiler, and merely slow down the code. In practice thiw wouldn't be noticeable compared to the cost of creating a new thread, though.
No, it should not be volatile. At the same time you are pointing at the valid issue. Detailed operation of the cache is described in the Intel/ARM/etc papers.
Nevertheless you can safely assume that the data WILL BE WRITTEN. Otherwise too many things will be broken. Several decades of experience tell that this is so.
If thread scheduler will start thread on the same core, the state of the cache will be fine, otherwise, if not, kernel will flush the cache. Otherwise, nothing will work.
Never use volatile for interaction between threads. It is an instruction on how to handle data inside the thread only (use a register copy or always reread, etc).
First, I think optimizer cannot change the order at expense of the correctness. CreateThread() is a function, parameter binidng for function calls happens before the call is made.
Secondly, volatile is not very helpful for the purpose you intend. Check out this article.
You're struggling into a non-problem, and are creating at least other two...
Don't worry about the parameter given to CreateThread: if they exist at the time the thread is created they exist until CreateThread returns. And since the thread who creates them does not destroy them, they are also available to the other thread.
The problem now becomes who and when they will be destroyed: You create them with new so they will exist until a delete is called (or until the process terminates: good memory leak!)
The process terminate when its main thread terminate (and all other threads will also be terminated as well by the OS!). And there is nothing in your main that makes it to wait for the other thread to complete.
Beware when using low level API like CreateThread form languages that have thir own library also interfaced with thread. The C-runtime has _beginthreadex. It call CreateThread and perform also other initialization task for the C++ library you will otherwise miss. Some C (and C++) library function may not work properly without those initializations, that are also required to properly free the runtime resources at termination. Unsing CreateThread is like using malloc in a context where delete is then used to cleanup.
The proper main thread bnehavior should be
// create the data
// create the other thread
// // perform othe task
// wait for the oter thread to terminate
// destroy the data
What the win32 API documentation don't say clearly is that every HANDLE is waitable, and become signaled when the associate resource is freed.
To wait for the other thread termination, you main thread will just have to call
WaitForSingleObject(hthread,INFINITE);
So the main thread will be more properly:
{
data* pdata = new data;
HANDLE hthread = (HANDLE)_beginthreadex(0,0,yourprocedure, pdata,0,0);
WaitForSingleObject(htread,INFINITE);
delete pdata;
}
or even
{
data d;
HANDLE hthread = (HANDLE)_beginthreadex(0,0,yourprocedure, &d,0,0);
WaitForSingleObject(htread,INFINITE);
}
I think the question is valid in another context.
As others have pointed out using a struct and the contents is safe (although access to the data should by synchronized).
However I think that the question is valid if you hav an atomic variable (or a pointer to one) that can be changed outside the thread. My opinion in that case would be that volatile should be used in this case.
Edit:
I think the examples on the wiki page are a good explanation http://en.wikipedia.org/wiki/Volatile_variable
So recently I started thinking about a way of improving speed (vs cpu usage) in a program which is extensible by DLL's which you can built with the provided SDK (Software Development Kit) in C++.
I started doing research on threading data and then writing to global variables, where - if needed - the main thread would just call a variable, and not execute a whole function (the thread does the stuff).
I was actually surprised by my results, because I expected the thread to crash the application - however it didn't.
I started a discussion on the application's developer forum - we got to the point that stated:
"The rule for threads is: If it crashes, it's wrong, if it doesn't crash, it's probably still wrong." and:
"Actually, that code probably won't crash, but it can corrupt variables. I've heard stories of multi-threaded programs running for months with no issues before a race-hazard occurred."
Well, can 'GETS' actually cause race conditions?
The main application (SA-MP , San Andreas Multiplayer) is single threaded, and compiled like that.
The code I used for my tests:
[C++]
#ifdef OS_WINDOWS
void Thread::BackgroundCalculator( void *unused )
#else
void *Thread::BackgroundCalculator( void *unused )
#endif
{
float X;
float Y;
float Z;
while( true )
{
if(ENABLED == false)
{
continue;
}
for(int i = 0; i < MAX_PLAYERS; ++i)
{
if(IsPlayerConnected(i) == false)
{
speed[i] = -1.0f;
continue;
}
if(IsPlayerInAnyVehicle(i) == true)
{
GetVehicleVelocity(GetPlayerVehicleID(i),&X,&Y,&Z);//Is actually used by MAIN APPLICATION thread too... so should cause race condition?
}
else
{
GetPlayerVelocity(i,&X,&Y,&Z);//Is actually used by MAIN APPLICATION thread too... so should cause race condition?
}
speed[i] = sqrt(X*X+Y*Y+Z*Z);//called from my code.. thread
}
SLEEP(30);
}
EXIT_THREAD();//should be never reached..
}
static cell AMX_NATIVE_CALL n_GetSpeed( AMX* amx, cell* params )
{
return amx_ftoc(speed[params[1]]);//returning to main thread, ftoc = FloatToCell
}
and when calling VERY MANY TIMES "n_GetSpeed" from the virtual machine (.amx file). It doesn't crash.
I also tried calling GetPlayerVelocity/GetVehicleVelocity from the main thread and my thread as much as possible at the same time. and still doesn't crash. totally not what I'd expect.
So, when we got to the point where somebody said a race-condition will occur, I would like to know how to cause one (force a race condition?). (in C/C++ ofcourse)
__
The code I am making is always open-source and available from my page, this too:
http://gpb.googlecode.com/files/ThreadTest_R100.zip
Just if you need the whole code ;)
__
Extra note: the thing is.. That I only access variables, not change, the only thing I change is the speed variable and it's ONLY done in the second thread.
Without knowing much about the application you are modifying. It could potentially cause a crash.
You say that you only read, so everything should be fine. BUT, the main thread (the original program) will most definitely change the variables. One thing that could happen is that after you call IsPlayerInAnyVehicle and it returns TRUE, it changes to FALSE, or the vehicle changes, or the player dies, or the player quits, ... Your call to GetVehicleVelocity, GetPlayerVehicleID or GetPlayerVelocity might therefore be called under erroneous circumstances. Will this lead to a crash? Who knows. But at least, the code is not 100% healthy.
EDIT: It is impossible to know whether this code is thread-safe without knowing how the methods you call are implemented. Put weak memory ordering into the game and all bets are off, without proper memory barriers.
Is the following
int BlkArray::GetNthBlockA(unsigned int n, const Block *&pfb, int &maxIndex) const {
if (n + 1 >= (unsigned int)formattingPivots.GetCount()) return -1;
pfb = formattingPivots.GetNthBlckB(n);
maxIndex = formattingPivots.GetNthInt(n + 1) - 1;
return formattingPivots.GetNthInt(n);
}
thread safe considering:
formattingPivots.GetNthBlckB(n), formattingPivots.GetNthInt(n + 1), formattingPivots.GetNthInt(n) and formattingPivots.GetCount() are all const methods.
I call GetNthBlock() from 2 threads, when thread1 calls and returns an usual Block I notice a side effect in thread2.
const Block *&pfb is passed as follows from each thread's worker method:
int maxIndex;
const Block *pfb = null;
pStoredBlcks->GetNthBlockA(blockBreakIndex, pfb, maxIndex);
I'm concerned const might be causing an unintended effect in persisting between both workers' bodies. I'm 98% the bugs I get are from the code above but, being peculiar to multithreading I can't get much more sure.
I'm getting near my question limit for 24 hrs, on one more thing, if it might help. Is static_cast<> thread safe? (Silly? yeah but I wrote C for years) I ask because of:
const Block *GetNthblckB(int n) const {
return static_cast<const Block*>(Blocks.GetAt(n));//Returns `Object`* without cast.
}
3am___
Thanks for the encouragement guys. I just surrounded that call with a CritSecMonitor and I still have the side effect. Short of reading the valgrind manual I better catch some zz's.
The #1 fact of thread safety: If two functions f() and g() are both thread safe, then the following function is not necessarily thread safe:
// h might not be thread-safe!
void h()
{
f(); // f is thread-safe
g(); // g is thread-safe
}
So you will have to prove thread-safety based on the contents of the functions GetNthBlckB, GetNthInt, etc. I don't know what these methods do, so I don't know if they are thread-safe or not (const has nothing to do with it). It looks like it is not thread-safe to me.
Is Blocks.GetAt() an immutable method (doesn't change any internal state)? It may not be, if it is using a cache to read from a database or from a file, for instance.
Also, the answer to your question would also depend on when the data was initialized.
Is it before any threads are spawned?
Also, I recommend that you using valgrind's drd and helgrind regularly on your project to help you find current bugs as well as preventing future threading bugs from getting into your project.
Last Recommendation
One last suggestion, when in doubt about thread-safety, put in your own mutex.
If you can show that it runs fine with the mutex then you can isolate the bug/false assumptions/critical section(s).
In answer to my question, I thought someone else had already said this:
Don't assume any library function is thread safe unless it says it is.
My 98% guess was wrong and the thread unsafe method lay elsewhere in a library instance method using completely seperate objects but being called from two threads. There must have been a static variable in there somewhere as the call stacks where it would crash (very rarely) looked to be deep inside library code.
I need to have a class with one activity that is performed once per 5 seconds in its own thread. It is a web service one, so it needs an endpoint to be specified. During the object runtime the main thread can change the endpoint. This is my class:
class Worker
{
public:
void setEndpoint(const std::string& endpoint);
private:
void activity (void);
mutex endpoint_mutex;
volatile std::auto_ptr<std::string> newEndpoint;
WebServiceClient client;
}
Does the newEndpoint object need to be declared volatile? I would certainly do it if the read was in some loop (to make the complier not optimize it out), but here I don't know.
In each run the activity() function checks for a new endpoint (if a new one is there, then passes it to the client and perform some reconnection steps) and do its work.
void Worker::activity(void)
{
endpoint_mutex.lock(); //don't consider exceptions
std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint);
if (NULL != ep.get())
{
client.setEndpoint(*ep);
ep.reset(NULL);
endpoint_mutex.unlock();
client.doReconnectionStuff();
client.doReconnectionStuff2();
}
else
{
endpoint_mutex.unlock();
}
client.doSomeStuff();
client.doAnotherStuff();
.....
}
I lock the mutex, which means that the newEndpoint object cannot change anymore, so I remove the volatile class specification to be able to invoke const methods.
The setEndpoint method (called from another threads):
void Worker::setEndpoint(const std::string& endpoint)
{
endpoint_mutex.lock(); //again - don't consider exceptions
std::auto_ptr<std::string>& ep = const_cast<std::auto_ptr<string> >(newEndpoint);
ep.reset(new std::string(endpoint);
endpoint_mutex.unlock();
}
Is this thing thread safe? If not, what is the problem? Do I need the newEndpoint object to be volatile?
volatile is used in the following cases per MSDN:
The volatile keyword is a type qualifier used to declare that an
object can be modified in the program by something such as the
operating system, the hardware, or a concurrently executing thread.
Objects declared as volatile are not used in certain optimizations
because their values can change at any time. The system always reads
the current value of a volatile object at the point it is requested,
even if a previous instruction asked for a value from the same object.
Also, the value of the object is written immediately on assignment.
The question in your case is, how often does your NewEndPoint actually change? You create a connection in thread A, and then you do some work. While this is going on, nothing else can fiddle with your endpoint, as it is locked by a mutex. So, per my analysis, and from what I can see in your code, this variable doesn't necessarily change enough.
I cannot see the call site of your class, so I don't know if you are using the same class instance 100 times or more, or if you are creating new objects.
This is the kind of analysis you need to make when asking whether something should be volatile or not.
Also, on your thread-safety, what happens in these functions:
client.doReconnectionStuff();
client.doReconnectionStuff2();
Are they using any of the shared state from your Worker class? Are they sharing and modifying any other state use by another thread? If yes, you need to do the appropriate synchronization.
If not, then you're ok.
Threading requires some thinking, you need to ask yourself these questions. You need to look at all state and wonder whether or not you're sharing. If you're dealing with pointers, then you need wonder who own's the pointer, and whether you're ever sharing it amongst threads, accidentally or not, and act accordingly. If you pass a pointer to a function that is run in a different thread, then you're sharing the object that the pointer points to. If you then alter what it points to in this new thread, you are sharing and need to synchronize.