passing structure object as parameter to a thread - c++

This code runs successfully and MQStruct constructor initialized the values as well, I can see in ExecuteThread function but in TestFunction, I get the garbage values for MQStruct.
I am passing address of struct "&MQStructObj" to _beginthreadex for parameters and This is the problem I guess
struct MQStruct {
MQStruct()
{
pointer=NULL;
serviceName=NULL;
durability=0;
msgType=0;
msgHeader=0;
msgId=NULL;
payload=NULL;
payloadSize=0;
ttl=0;
priority=0;
}
void* pointer;
wchar_t *serviceName;
int durability;
int msgType;
int msgHeader;
wchar_t *msgId;
wchar_t *payload;
int payloadSize;
int ttl;
int priority;
};
int ExecuteThread() {
HANDLE heartBeatThread;
unsigned int hbThreadID;
int result = 0;
MQStruct MQStructObj;
MQStructObj.pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, &MQStructObj, 0/*CREATE_SUSPENDED*/, &hbThreadID);
if ( heartBeatThread == 0 )
{
result = -1;
LogEvent(DEBUG_LOG,0, "Fail to create thread");
}
CloseHandle(heartBeatThread);
return result;
}

You guessed correctly.
You're passing the address of a local variable to your thread-proc-startup, then leaving scope (and destroying the object in the process). References to this object in your thread proc are there-after undefined behavior.
Dynamically allocate one with new and let the thread proc delete it.

MQStructObj is declared on the stack so will go out of scope and potentially be overwritten as soon as ExecuteThread completes.
If you want to use a stack object here, you'll need to add some synchronisation to allow your new thread to copy from MQStructObj before ExecuteThread returns.
Alternatively, normally preferably, you could allocate MQStructObj dynamically and leave the new thread to clean it up at its leisure
MQStruct* MQStructObj = new MQStruct();
MQStructObj->pointer=this;
heartBeatThread = (HANDLE)_beginthreadex(NULL, 0 , &TestFunction, MQStructObj, 0, &hbThreadID);
if ( heartBeatThread == 0 ) { // error
delete MQStructObj;
result = -1;
}
// ownership of MQStructObj transferred to new thread

Related

an static function used in StringHashTable thread-safe?

I have got an StringHashTable class from
http://preshing.com/20110603/hash-table-performance-tests/
The following are parts of source :
class StringHashTable
{
static uint fnv1Hash(const char *key)
{
unsigned int hash = 2166136261ul;
for (const char *s = key; *s; s++)
hash = (16777619 * hash) ^ (*s);
return hash;
};
uint &operator[](const char *key)
{
uint hash = fnv1Hash(key) & (m_tableSize - 1);
Bucket *firstBucket = m_table + hash;
Bucket *b = firstBucket;
if (b->key)
{
do
{
if (strcmp(b->key, key) == 0)
return b->value;// Found existing bucket
b = b->next;
} while (b);
}
..........
}
}
Suppose that I have the global var :
StringHashTable hashtable(1024) ; //m_tableSize now 1024
And then the following is in main :
hashtable["0000"] = 0 ;
....
hashtable["9999"] = 9999 ;
After fill in all the data I need , thread 1 to n will get value according to key
while(1)
{
s = get(); //return string like "0000" ... "9999"
echo << hashtable[s.c_str()] << endl ;
}
I wonder if the StringHashTable would work fine in thread at first ,
because the function fnv1Hash is static , on second thought , there is no
static member data in this StringHashTable , so while thread1 is doing
hashtable["0000"] and thread2 is doing hashtable["9999"] at the very same time
both thread1 are calling fnv1Hash they will both get the right hash returned !!!
My question is : different thread call static uint fnv1Hash(const char *key) with
different key at the very same time still work fine ? In StringHashTable , fnv1Hash
is static for any reason ?!
The function fnv1Hash() doesn't access any non-local state other than the data pointed to by key. Assuming the content of the array key points to isn't written to concurrently, there is no threading issue. Of course, if another thread writes to the array pointed to by key, all bets are off.
Given that fnv1Hash() does access any of the object's data it doesn't need a this pointer. Thus, it is made static to indicate both to the human reader and the compiler that the objects won't be accessed implicitly. For the compiler the upshot is that it doesn't need to pass a this pointer.

Creation of thread with an dynamic argument

I am creating a thread from main thread with an dynamic allocated object as an argument. But if we are deleting this dynamic memory allocated object in main thread then how can we find out a object is deleted in created thread.
main thread code :
int CLocalReader::Run()
{
TReaderArgument *readerArg = new TReaderArgument;
readerArg->iFinished = &theFinishedACE;
readerArg->iSelf = this;
#ifdef WIN32
if (ACE_Thread::spawn((ACE_THR_FUNC)LocalReaderFunc, readerArg) == -1)
{
ACE_DEBUG((LM_DEBUG,"Could not start reader\n"));
delete readerArg;
readerArg = NULL;
}
#else
if (ACE_Thread_Manager::instance()->spawn(ACE_THR_FUNC (LocalReaderFunc), readerArg, THR_NEW_LWP | THR_DETACHED) < 0)
{
ACE_DEBUG((LM_DEBUG,"Could not start reader\n"));
delete readerArg;
readerArg = NULL;
}
#endif
return KErrNone;
}
static void *ReaderFunc(void *arg)
{
ASSERT(arg);
ACE_Thread::yield();
ACE_OS::sleep(ACE_Time_Value(0, STARTUP_TIME));
TReaderArgument *rarg = (TReaderArgument *)arg;
CLocalReader *self = static_cast<CLocalReader *>(rarg->iSelf);
int *finished = rarg->iFinished;
while (!(*finished))
{
if( self->GetData() != KErrorNone )
{
ACE_DEBUG((LM_DEBUG, "%D LocalReader : Error receiving data\n"));
}
}
return 0;
}
if in above code , this object is deleted then how we can check in thread function self object is deleted
Use reference counting like in COM. When the main thread is done with the object, it can set a flag "deleted" and release the object. The object will not be deleted yet, because the thread is still holding the reference count. But, the thread can check the flag and release the object if the flag is set. The reference count will drop to 0 and the object will commit suicide by calling delete this;

storing struct as value using CFDictionarySetValue()

Iam new to using Core Foundations. I want to use dictionary to store some key value pair. The value must be a pointer to a struct. This pointer is pointing to dynamically allocated buffer.
CFMutableDictionaryRef init_hash_table() {
return CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
This is used to create the dictionary and the return value is stored as global variable.
CFNumberRef
create_hash_key(int sd) {
return CFNumberCreate(NULL, kCFNumberIntType, &sd);
}
int
add_hash_entry(CFMutableDictionaryRef dict, int sd, void *pkt) {
CFNumberRef key = create_hash_key(sd);
CFDictionarySetValue(dict, key, pkt);
return 0;
}
When I execute this code, I get segfault. I see that pkt has a valid address and key seems to be created. Does anyone know how to assign a pointer to value part?
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000011
0x00007fff8c9f339f in objc_msgSend_fixup ()
Any ideas?
The problem is the kCFTypeDictionaryValueCallBacks argument. From the documentation:
kCFTypeDictionaryValueCallBacks
Predefined CFDictionaryValueCallBacks structure containing a set of
callbacks appropriate for use when the values in a CFDictionary are
all CFType-derived objects.
So in your case, CFRetain() is called on the pointer when the value is added to the
dictionary. This causes the crash because the pointer does not point to a CoreFoundation
object.
You can create the dictionary with
CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
instead, so that no "reference counting" will be done on the value.
Alternatively, you can wrap the pointer into a CFDataRef and put that into the
dictionary.
In both cases it is your responsibility that the pointer is still valid
when the value is retrieved from the dictionary later.
Here is a simple example how you could implement refcounting for your custom objects:
typedef struct {
int refcount;
int val;
} mystruct;
const void *myretain(CFAllocatorRef allocator, const void *value)
{
mystruct *p = (mystruct *)value;
p->refcount++;
return p;
}
void myrelease(CFAllocatorRef allocator, const void *value)
{
mystruct *p = (mystruct *)value;
if (p->refcount == 1)
free(p);
else
p->refcount--;
}
int main(int argc, const char * argv[])
{
mystruct *p = malloc(sizeof(*p));
p->refcount = 1;
p->val = 13;
CFDictionaryValueCallBacks vcb = { 0 , myretain, myrelease, NULL, NULL };
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &vcb);
int sd = 13;
CFNumberRef key = CFNumberCreate(NULL, kCFNumberIntType, &sd);
CFDictionarySetValue(dict, key, p);
// refcount == 2
myrelease(NULL, p);
// refcount == 1
mystruct *q = CFDictionaryGetValue(dict, key);
// refcount is still 1, "GetValue" does not increment the refcount
CFRelease(dict);
// object is deallocated
return 0;
}

Initialize pid_t variable

I have an error reported by Valgrind:
==5644== Conditional jump or move depends on uninitialised value(s)
This is happening for a variable of type pid_t.
My code is the following:
GmpPipePlayer::GmpPipePlayer( IOBase *pIO, Referee *pBack, PieceColor pc, int size, const DataBoard *pBd, int handicap, const char *cmd_line, int bDebug )
: GmpPlayer(pIO, pBack, pc, size, pBd, handicap, bDebug)
{
int down[2], up[2];
pid_t _pid; //here the var is declared
pipe(down);
pipe(up);
_pid = fork();
if (_pid < 0)
exit(1);
if (_pid == 0)
{
close(down[1]);
close(up[0]);
dup2(down[0], 0);
dup2(up[1], 1);
execl("/bin/sh", "sh", "-c", cmd_line, NULL);
_exit(1);
}
close(down[0]);
close(up[1]);
_down = down[1];
_up = up[0];
_reader_thd = new Thread(reader_wrapper, this);
}
GmpPipePlayer::~GmpPipePlayer()
{
if (_pid > 0) //valgrind is reporting that the error is here!!
{
kill(_pid, SIGTERM);
_pid = 0;
}
if (_up)
{
close(_up);
_up = 0;
}
if (_down)
{
close(_down);
_down = 0;
}
delete _reader_thd
}
So, I think the problem is the _pid is not initialized, how should initialize this variable? I tried in this way:
pid_t _pid=0;
but this is still causing the same error. That piece of code is called many times during the process.
It appears that you have two variables called _pid - the local that you declared in the constructor:
pid_t _pid; //here the var is declared
and the one that you access in the destructor:
if (_pid > 0) //valgrind is reporting that the error is here!!
These variables are not the same: the one that you access in the destructor must be a global or an instance variable (more likely).
Since you rely on _pid to pass the state from the constructor to the destructor, you need to remove the local declaration from the constructor, and initialize the other _pid as appropriate. If it is an instance variable, add its initialization to the initializer list, like this:
GmpPipePlayer::GmpPipePlayer( IOBase *pIO, Referee *pBack, PieceColor pc, int size, const DataBoard *pBd, int handicap, const char *cmd_line, int bDebug )
: GmpPlayer(pIO, pBack, pc, size, pBd, handicap, bDebug), _pid(0) {
... // HERE ------------------^
}

Thread Argument Problem

I have working on multithreaded application I am passing IMAGETHREADINFO structure in thread here nSock is showing garbage value. What is the problem here.pointer to IMAGETHREADINFO is declared as member variable of CServerConnectionMgr class.
typedef struct
{
int nScok;
CServerConnectionMgr* pConMgr;
}IMAGETHREADINFO;
void StartImageThread(SOCKET nSock)
{
stThreadInfo = new IMAGETHREADINFO;
stThreadInfo.pConMgr = this;
stThreadInfo.nScok = nSock;
m_hRecordImageThread = CreateThread ( NULL,0, (LPTHREAD_START_ROUTINE)StreamImageThread,(void*)&stThreadInfo, 0,&m_nRecordImageThreadID);
if ( NULL == m_hRecordImageThread)
{
return;
}
int CServerConnectionMgr::StreamImageThread(void *args)
{
IMAGETHREADINFO *pImageThreadInfo = (IMAGETHREADINFO*)&args;
}
This is variable pImageThreadInfo->nSock showing some garbage value
This pImageThreadInfo->pConMgr is coming correctly
I this is showing wrong value
(void*)&stThreadInfo is a pointer to the stThreadInfo pointer. You likely want to remove the &
And then, also change IMAGETHREADINFO *pImageThreadInfo = (IMAGETHREADINFO*)&args;, remove the &