Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

LINK TO THIS FORUM!

Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

Partner With Us!

"Best Of Breed" Forums Add Stickiness To Your Site
Partner Button
(Download This Button Today!)

Feedback

"...I don't think testimonials would have enticed me to become a member, or even use the site for that matter. I use the site for a learning experience..."

Geography

Where in the world do Tek-Tips members come from?

Segfault with threadsHelpful Member!(2) 

mbaranski (Programmer)
1 Jun 01 12:22
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 "ErrorLog.h"
#include "MysqlConsumer.h"
#include "InformixProducer.h"
#include "InformixTable.h"

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("/etc/carma.conf", &env);

  /* Put Informix server (Top Level) in the environment */
  sprintf(informixServer, "INFORMIXSERVER=%s", (*env.find("INFORMIX_SERVER")).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 "HASTA PRONTO, AMIGO
  */
  mysql_one.setHost("");
  mysql_one.setUsername((*env.find("MYSQL_USERNAME")).second.c_str());
  mysql_one.setPassword((*env.find("MYSQL_PASSWORD")).second.c_str());
  mysql_one.setDbname((*env.find("MYSQL_DBNAME")).second.c_str());
  mysql_one.prepare();
  mysql_one.connect();

  mysql_two.setHost("");
  mysql_two.setUsername((*env.find("MYSQL_USERNAME")).second.c_str());
  mysql_two.setPassword((*env.find("MYSQL_PASSWORD")).second.c_str());
  mysql_two.setDbname((*env.find("MYSQL_DBNAME")).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("INFORMIX_SERVER")).second);
  informix_p_one.setUserName((*env.find("INFORMIX_USERNAME")).second);
  informix_p_one.setPassWord((*env.find("INFORMIX_PASSWORD")).second);
  informix_p_one.setDbName((*env.find("INFORMIX_DBNAME")).second);
  informix_p_one.setMysqlName((*env.find("MYSQL_DBNAME")).second);
  informix_p_one.serverType = 0;
  
  sptableVector = parseTableString( (*env.find("SPECIAL_TABLES")).second, ':');
  shtableVector = parseTableString( (*env.find("SUB_HOST_TABLES")).second, ':');
  tltableVector = parseTableString( (*env.find("TOP_LEVEL_TABLES")).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, "DROP TABLE IF EXISTS " +(*env.find("MYSQL_DBNAME")).second
    + "." + 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, "DBPATH=");
  i = loSubHosts.size();
  for(int k = 0; k < i; k++){
    //    cerr << loSubHosts[k] << endl;
    sprintf(additionalServers, "%s//%s:", 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("INFORMIX_USERNAME")).second);
    informix_p_sh[k].setPassWord((*env.find("INFORMIX_PASSWORD")).second);
    informix_p_sh[k].setDbName((*env.find("INFORMIX_DBNAME")).second);
    informix_p_sh[k].setMysqlName((*env.find("MYSQL_DBNAME")).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 << "Created Informix thread " << 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 << "Join informix thread " << 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, "HASTA PRONTO, AMIGO");
  // cerr << "Put!" << endl;
  
  /* Join them all, wait until they return */
  pthread_join(pt_one, &retval);
  pthread_join(pt_two, &retval);
  
  cerr << "Done!" << endl;
}


Disclaimer:
Beware: Studies have shown that research causes cancer in lab rats.

Helpful Member!(2)  rbobbitt (Programmer)
1 Jun 01 12:42
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
http://home.earthlink.net/~bobbitts
mbaranski (Programmer)
1 Jun 01 12:48
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.

Lim (Programmer)
5 Jun 01 11:05
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.
Masi (Programmer)
8 Jun 01 4:50
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

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Back To Forum

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close