Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Segfault with threads 2

Status
Not open for further replies.

mbaranski

Programmer
Nov 3, 2000
421
0
0
US
Anyone have any idea why the following source code segfaults after it exits? It prints Done! (The last line) and then segfaults. All of the threads join up and then it gets a sigsegv.?. This is very confusing.

MWB.


#include <multimap.h>
#include <vector>
#include <string>
#include <deque>
#include <iostream.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>

#include &quot;ErrorLog.h&quot;
#include &quot;MysqlConsumer.h&quot;
#include &quot;InformixProducer.h&quot;
#include &quot;InformixTable.h&quot;

extern int MysqlConsumer::numberOfMysqlThreadsActive;
extern void *consume(void *);
extern void *fill_from_sub_host(void *);
extern void setEnv(string, multimap<string, string> *);
extern void put(prodcons *, string);
extern vector<string> parseTableString(string, char);

prodcons p;

void main()
{
void *retval;
vector<string> tltableVector; /* This is just temporary */
vector<string> shtableVector; /* This is just temporary */
vector<string> sptableVector; /* This is just temporary */
multimap<string, string> env; /* The config file is stored here */
int my_threads;
int ifx_threads;
int i;
char informixServer[32];
char additionalServers[1024];
vector<string> loSubHosts;

/* Alloc these according to the config file
we need a MysqlConsumer for each mysql
thread, and InformixProducer for each
sub host plus one for the top level host
and some threads, too
*/
MysqlConsumer t;

/* These are the mysql thread defs
and the pthreads that they use
*/
MysqlConsumer mysql_one(&p);
MysqlConsumer mysql_two(&p);
pthread_t pt_one;
pthread_t pt_two;

/* These are the informix producers
and their pthreads
*/
InformixProducer informix_p_one(&p);
InformixProducer informix_p_sh[21];

pthread_t pt_three;
pthread_t pt_sh[21];

MysqlConsumer::numberOfMysqlThreadsActive = 0;

/* Read the config file into the env map */
setEnv(&quot;/etc/carma.conf&quot;, &env);

/* Put Informix server (Top Level) in the environment */
sprintf(informixServer, &quot;INFORMIXSERVER=%s&quot;, (*env.find(&quot;INFORMIX_SERVER&quot;)).second.c_str());
putenv(informixServer);

/* Allocate memory for all the threads we'll need. */
my_threads = 2;
// pthread_mutex_unlock(&p.lock);

/* Set up the threads and set their information
After this, we fork off the mysql threads
and they are ready to pull stuff out of the
buffer, until they see &quot;HASTA PRONTO, AMIGO
*/
mysql_one.setHost(&quot;&quot;);
mysql_one.setUsername((*env.find(&quot;MYSQL_USERNAME&quot;)).second.c_str());
mysql_one.setPassword((*env.find(&quot;MYSQL_PASSWORD&quot;)).second.c_str());
mysql_one.setDbname((*env.find(&quot;MYSQL_DBNAME&quot;)).second.c_str());
mysql_one.prepare();
mysql_one.connect();

mysql_two.setHost(&quot;&quot;);
mysql_two.setUsername((*env.find(&quot;MYSQL_USERNAME&quot;)).second.c_str());
mysql_two.setPassword((*env.find(&quot;MYSQL_PASSWORD&quot;)).second.c_str());
mysql_two.setDbname((*env.find(&quot;MYSQL_DBNAME&quot;)).second.c_str());
mysql_two.prepare();
mysql_two.connect();

MysqlConsumer::numberOfMysqlThreadsActive++;
MysqlConsumer::numberOfMysqlThreadsActive++;

pthread_create (&pt_one, NULL, consume, &mysql_one);
pthread_create (&pt_two, NULL, consume, &mysql_two);

/* Now the threads are running for mysql */
/* End of thread creation for mysql */

/* Create an InformixProducer thread... one for each server,
all at one time
*/
informix_p_one.setHostName((*env.find(&quot;INFORMIX_SERVER&quot;)).second);
informix_p_one.setUserName((*env.find(&quot;INFORMIX_USERNAME&quot;)).second);
informix_p_one.setPassWord((*env.find(&quot;INFORMIX_PASSWORD&quot;)).second);
informix_p_one.setDbName((*env.find(&quot;INFORMIX_DBNAME&quot;)).second);
informix_p_one.setMysqlName((*env.find(&quot;MYSQL_DBNAME&quot;)).second);
informix_p_one.serverType = 0;

sptableVector = parseTableString( (*env.find(&quot;SPECIAL_TABLES&quot;)).second, ':');
shtableVector = parseTableString( (*env.find(&quot;SUB_HOST_TABLES&quot;)).second, ':');
tltableVector = parseTableString( (*env.find(&quot;TOP_LEVEL_TABLES&quot;)).second, ':');

/* Process top level tables on top level host */
informix_p_one.setTopLevelTables(tltableVector);

/* Drop the sub host tables */
while(tltableVector.size() > 0){
put(&p, &quot;DROP TABLE IF EXISTS &quot; +(*env.find(&quot;MYSQL_DBNAME&quot;)).second
+ &quot;.&quot; + tltableVector[tltableVector.size()-1]);
tltableVector.pop_back();
}

/* Find what sub hosts are on the network */

informix_p_one.connect_once();
loSubHosts = informix_p_one.getSubHosts();
// cerr << loSubHosts.size() << endl;

// if(loSubHosts.size() == 0){

/* It's a single-host configuration */
informix_p_one.setSpecialTables(sptableVector);
informix_p_one.setSubHostTables(shtableVector);

//}

/* Set up the additinal servers environment variable */
sprintf(additionalServers, &quot;DBPATH=&quot;);
i = loSubHosts.size();
for(int k = 0; k < i; k++){
// cerr << loSubHosts[k] << endl;
sprintf(additionalServers, &quot;%s//%s:&quot;, additionalServers, loSubHosts[k].c_str());
informix_p_sh[k] = InformixProducer(&p);
informix_p_sh[k].serverType = 1;
}
putenv(additionalServers);

/* Start the top level thread */
pthread_create (&pt_three, NULL, fill_from_sub_host, &informix_p_one);

i = loSubHosts.size();
// cerr << endl << i << endl;
for(int k = 0; k < i; k++){
informix_p_sh[k].setHostName(loSubHosts[k]);
informix_p_sh[k].setUserName((*env.find(&quot;INFORMIX_USERNAME&quot;)).second);
informix_p_sh[k].setPassWord((*env.find(&quot;INFORMIX_PASSWORD&quot;)).second);
informix_p_sh[k].setDbName((*env.find(&quot;INFORMIX_DBNAME&quot;)).second);
informix_p_sh[k].setMysqlName((*env.find(&quot;MYSQL_DBNAME&quot;)).second);
informix_p_sh[k].serverType = 0;
informix_p_sh[k].setSpecialTables(sptableVector);
informix_p_sh[k].setSubHostTables(shtableVector);
/* Start the sub-host threads */
//cerr << &quot;Created Informix thread &quot; << k << endl;
pthread_create (&pt_sh[k], NULL, fill_from_sub_host, &informix_p_sh[k]);
}

/* This creates the informix thread (Top Level) */

/* When the informix threads return, shut the mysql ones down */
pthread_join(pt_three, &retval);
i = loSubHosts.size();
for(int k = 0; k < i; k++){
// cerr << &quot;Join informix thread &quot; << k << endl;
pthread_join(pt_sh[k], &retval);
}

/* Now, all tables on all servers are processed,
so we can do any general mysql stuff now
like create indexes, clean the badge table
and so forth.
*/

/* Tell the mysql threads we're done
and that they can go away
*/
put(&p, &quot;HASTA PRONTO, AMIGO&quot;);
// cerr << &quot;Put!&quot; << endl;

/* Join them all, wait until they return */
pthread_join(pt_one, &retval);
pthread_join(pt_two, &retval);

cerr << &quot;Done!&quot; << endl;
}

Disclaimer:
Beware: Studies have shown that research causes cancer in lab rats.
 
Try changing the return value of main() from void to int. In C++, main() returns an int. It may be that something untoward happens once the program ends because your compiler doesn't support this definition of main().

Russ
bobbitts@hotmail.com
 
This had no effect. I tried this and it still segfaults. It's something (I think) with the threads stuff, because it was working OK before I added like 5 threads, but they are all doing what they are supposed to and it's exiting right...

Anyway, thanks for your suggestion...
Disclaimer:
Beware: Studies have shown that research causes cancer in lab rats.
 
It is too long code. I had a similar case. In may case some default destructor (from Qt) was trying to delete empty object on exit. May be some static object has a destructor? It may nothing to do with thread. Just trace it or use purify if you have it.
 
Try to get more control of the allocation and deallocation process to indentify where the problem is.
I normally prefer to allocate objects in a initFunction and
deallocate them in a shutdownFunction.
Having to do with object and their destructor, the deallocation order can be important or, at least, you could better identify witch is the object that causes the seg-fault.
Also, try to get more control of threads.
Defying a cleaning function, checking their state, using mutex.

Think also that libraries we are using, sometimes have bugs!
So, isolating them, you can manage better situations like this.
Hope it wasn't boring
Masi
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top