[zeromq-dev] Assert when debugging, but not when executing

Claudio Carbone erupter at libero.it
Wed Jan 9 14:44:50 CET 2013


I've been having this problem the past couple of days: whenever I try to 
debug a program of mine I get an assert fail on a socket address.
There are a few curious facts about this problem:

-the program works perfectly when run normally
-the problem appears if the very same lines are in a child thread to 
which a pointer to the context is passed
     if the same lines are moved inside the main thread, no assert error 
on debugging
-the assert is apparently triggered by a correct address in an epgm 
subscriber

I wrote the simplest use case I could devise

/*
  * File:   main.cpp
  * Author: erupter
  *
  * Created on January 9, 2013, 2:03 PM
  */

/*
  * File:   main.cpp
  * Author: erupter
  *
  * Created on January 9, 2013, 2:03 PM
  */

#include <cstdlib>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <list>
#include <zmqcpp.h>
#define THREAD_CONTROL_IPC      "ipc://saetta_th_control"
#define MULTICAST_ADDRESS       "239.192.1.1"
#define MULTICAST_PORT          5678
#define ROUTER_PORT             5679
#define HEADER_CTRL             "CTRL"
#define HEADER_SERVER_INFO      "SERVER_INFO"

using namespace std;
std::string _local_ip_address;
std::stringstream ss;
// custom struct to hold parameters to pass to child threads
struct parameters{
     // pointer to context
     Zmqcpp::Context * zmqcont;
     // function pointer for callbacks
     void (*callback) (std::string);
     //ip string to connect to
     std::string ip;
     //if child should bind or connect
     int conntype;
     //topics to subscribe
     std::list<std::string> topics;
};

//child thread
void *th_subscriber (void * params);
//callback
void server_location_callback(std::string ip);
//service function to get the specified interface's address
static inline bool get_iface_address(std::string interf);
/*
  *
  */
int main(int argc, char** argv) {

     struct parameters myparams;
     printf( "Requested interface wlan0, attempting to fetch address...\n");
     if (!get_iface_address("wlan0"))
         return (EXIT_FAILURE);

     //create the pgm address chaining various parameters defined above 
plus the local ip address of the interface
     ss << "epgm://" << _local_ip_address << ";" << MULTICAST_ADDRESS << 
":" << MULTICAST_PORT << std::endl;

     //create context
     Zmqcpp::Context* mycontext = new Zmqcpp::Context(1);

     //fill the parameters structure
     myparams.ip = ss.str();
     ss.str("");
     ss.str(HEADER_SERVER_INFO);
     myparams.topics.insert(myparams.topics.end(),ss.str());
     myparams.conntype = ZMQCPP_CONNECT;
     myparams.zmqcont=mycontext;
     myparams.callback=&server_location_callback;

     //create the connection string for the control socket
     ss.str("");
     ss << THREAD_CONTROL_IPC;
     //create the control socket
     Zmqcpp::Publisher *ctrlpublisher = new Zmqcpp::Publisher(mycontext, 
THREAD_CONTROL_IPC, ZMQCPP_BIND);

     //create the child thread
     pthread_t th_hndl_subber;
     pthread_create(&th_hndl_subber, NULL, th_subscriber, (void 
*)&myparams);


     while(1)
     {
         //send control messages over the control socket
         ctrlpublisher->PubMsg(2,HEADER_CTRL,"Test");
         sleep(1);
     }


     //garbage collection
     void *status;
     pthread_join(th_hndl_subber, &status);
     printf("Main thread cleaning.\n");
     ctrlpublisher->~Publisher();
     mycontext->~Context();
     printf("Main thread cleaned succesfully.");
     return (EXIT_SUCCESS);
}

static inline bool get_iface_address(std::string interf)
{
     int s;
     struct ifreq ifr = {};
     s = socket(PF_INET, SOCK_DGRAM, 0);

     strncpy(ifr.ifr_name, interf.c_str(), sizeof(ifr.ifr_name));

     if (ioctl(s, SIOCGIFADDR, &ifr) >= 0)
     {
         _local_ip_address = inet_ntoa(((struct sockaddr_in 
*)&ifr.ifr_addr)->sin_addr);
         printf("Detected interface IP address is %s.\nCreating sockets 
on this address.\n", _local_ip_address.c_str());
         return true;
     }
     printf("Unable to get interface IP address: is the interface 
configured?\n");
     return false;

}

void *th_subscriber (void * params)
{
     //declare some service variables
     int th_continue=1;
     std::string server_ip;
     std::stringstream ss;
     std::string msgtype;
     std::string msgmaster = HEADER_SERVER_INFO;
     std::string temp;

     //recast the pointer to the parameter structure
     struct parameters *myparams = (struct parameters *) params;

     //create the subscriber for the real messages we would like to get
     // THIS IS WHAT TRIGGERS THE ASSERT DURING DEBUG
     Zmqcpp::Subscriber *msgsubber = new 
Zmqcpp::Subscriber(myparams->zmqcont,&(myparams->ip), myparams->conntype);

     //have it subscribe to each topic we are told to
     for (std::list<std::string>::iterator it = 
myparams->topics.begin(); it != myparams->topics.end(); it++)
     {
         cout << "Subscribing to <" << *it <<">"<<std::endl;
         printf("Subscribing to: <%s>\n",it->c_str());
         msgsubber->SubscribeTopic(*it);
     }


     ss.str("");
     ss << THREAD_CONTROL_IPC;

     //create the control subscriber over the specified ipc control 
address and subscribe it
     Zmqcpp::Subscriber *ctrlsubber = new 
Zmqcpp::Subscriber(myparams->zmqcont,THREAD_CONTROL_IPC, ZMQCPP_CONNECT);
     ctrlsubber->SubscribeTopic(HEADER_CTRL);

     sleep(1);
     while(th_continue==1)
     {

         //do something silly with the control messages
         ss.str("");
         ss << ctrlsubber->RecvMsg();
         msgtype.clear();
         msgtype = ss.str();
         if (!msgtype.compare(HEADER_CTRL))
         {
             ss.str("");
             ss << "Control message: " << ctrlsubber->RecvMsg();
             temp.clear();
             temp.assign(ss.str());
             myparams->callback(temp.c_str());
             if (temp.compare("Control message: KILL")==0)
                 th_continue=0;

         }
     }
     //child thread garbage collection
     printf("Child thread cleaning resources.\n");
     ctrlsubber->~Subscriber();
     //msgsubber->~Subscriber();
     printf("Child thread terminating.\n");
     return(EXIT_SUCCESS);

}

void server_location_callback(std::string ip)
{

     cout << ip.c_str() <<  std::endl;
}


but nevertheless you would need my library to execute the code 
(https://github.com/erupter/saettang).
This clearly displays the problem: it runs correctly, but gives the 
assert error when attempting to debug.
Invalid argument (session_base.cpp:490)

If you comment out lines 123 to 129 you can debug the application 
without problems.
With those lines you can't debug, but you can run it and it works.

Appreciate any help.
Thank you
Claudio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20130109/45714cf2/attachment.htm>


More information about the zeromq-dev mailing list